fixing strict TS stuff

This commit is contained in:
MathMan05 2024-08-20 09:21:24 -05:00
parent 0102ddbeb4
commit a969887ddb
14 changed files with 571 additions and 411 deletions

View file

@ -72,6 +72,7 @@ class Voice {
return 0; return 0;
}; };
} }
return new Function();
} }
play() { play() {
if (this.playing) { if (this.playing) {

View file

@ -98,7 +98,9 @@ class Channel {
copy.classList.add("copybutton", "svgtheme"); copy.classList.add("copybutton", "svgtheme");
copycontainer.append(copy); copycontainer.append(copy);
copycontainer.onclick = _ => { copycontainer.onclick = _ => {
navigator.clipboard.writeText(text.textContent); if (text.textContent) {
navigator.clipboard.writeText(text.textContent);
}
}; };
div.append(copycontainer); div.append(copycontainer);
const update = () => { const update = () => {
@ -180,8 +182,14 @@ class Channel {
console.error("Uh..."); console.error("Uh...");
} }
try { try {
const html = snowflake.getObject().buildhtml(this.messageids.get(this.idToPrev.get(snowflake))); const prev = this.idToPrev.get(snowflake);
return html; if (prev) {
const messgage = this.messageids.get(prev);
if (messgage) {
const html = snowflake.getObject().buildhtml(messgage);
return html;
}
}
} }
catch (e) { catch (e) {
console.error(e); console.error(e);
@ -209,7 +217,9 @@ class Channel {
this.headers = this.owner.headers; this.headers = this.owner.headers;
this.name = json.name; this.name = json.name;
this.snowflake = new SnowFlake(json.id, this); this.snowflake = new SnowFlake(json.id, this);
this.parent_id = new SnowFlake(json.parent_id, undefined); if (json.parent_id) {
this.parent_id = SnowFlake.getSnowFlakeFromID(json.parent_id, Channel);
}
this.parent = null; this.parent = null;
this.children = []; this.children = [];
this.guild_id = json.guild_id; this.guild_id = json.guild_id;
@ -222,7 +232,10 @@ class Channel {
} }
; ;
this.permission_overwrites.set(thing.id, new Permissions(thing.allow, thing.deny)); this.permission_overwrites.set(thing.id, new Permissions(thing.allow, thing.deny));
this.permission_overwritesar.push([SnowFlake.getSnowFlakeFromID(thing.id, Role), this.permission_overwrites.get(thing.id)]); const permission = this.permission_overwrites.get(thing.id);
if (permission) {
this.permission_overwritesar.push([SnowFlake.getSnowFlakeFromID(thing.id, Role), permission]);
}
} }
this.topic = json.topic; this.topic = json.topic;
this.nsfw = json.nsfw; this.nsfw = json.nsfw;
@ -253,15 +266,16 @@ class Channel {
if (!this.hasPermission("VIEW_CHANNEL")) { if (!this.hasPermission("VIEW_CHANNEL")) {
return false; return false;
} }
return this.lastmessageid !== this.lastreadmessageid && this.type !== 4 && !!this.lastmessageid.id; return this.lastmessageid !== this.lastreadmessageid && this.type !== 4 && !!this.lastmessageid;
} }
hasPermission(name, member = this.guild.member) { hasPermission(name, member = this.guild.member) {
if (member.isAdmin()) { if (member.isAdmin()) {
return true; return true;
} }
for (const thing of member.roles) { for (const thing of member.roles) {
if (this.permission_overwrites.get(thing.id)) { const premission = this.permission_overwrites.get(thing.id);
let perm = this.permission_overwrites.get(thing.id).getPermission(name); if (premission) {
let perm = premission.getPermission(name);
if (perm) { if (perm) {
return perm === 1; return perm === 1;
} }
@ -274,7 +288,10 @@ class Channel {
} }
get canMessage() { get canMessage() {
if ((0 === this.permission_overwritesar.length) && this.hasPermission("MANAGE_CHANNELS")) { if ((0 === this.permission_overwritesar.length) && this.hasPermission("MANAGE_CHANNELS")) {
this.addRoleToPerms(this.guild.roles.find(_ => _.name === "@everyone")); const role = this.guild.roles.find(_ => _.name === "@everyone");
if (role) {
this.addRoleToPerms(role);
}
} }
return this.hasPermission("SEND_MESSAGES"); return this.hasPermission("SEND_MESSAGES");
} }
@ -282,12 +299,15 @@ class Channel {
this.children.sort((a, b) => { return a.position - b.position; }); this.children.sort((a, b) => { return a.position - b.position; });
} }
resolveparent(guild) { resolveparent(guild) {
this.parent = guild.channelids[this.parent_id?.id]; const parentid = this.parent_id?.id;
if (!parentid)
return false;
this.parent = guild.channelids[parentid];
this.parent ??= null; this.parent ??= null;
if (this.parent !== null) { if (this.parent !== null) {
this.parent.children.push(this); this.parent.children.push(this);
} }
return this.parent === null; return this.parent !== null;
} }
calculateReorder() { calculateReorder() {
let position = -1; let position = -1;
@ -301,8 +321,8 @@ class Channel {
if (thing.move_id && thing.move_id !== thing.parent_id) { if (thing.move_id && thing.move_id !== thing.parent_id) {
thing.parent_id = thing.move_id; thing.parent_id = thing.move_id;
thisthing.parent_id = thing.parent_id; thisthing.parent_id = thing.parent_id;
thing.move_id = undefined; thing.move_id = null;
console.log(this.guild.channelids[thisthing.parent_id]); console.log(this.guild.channelids[thisthing.parent_id.id]);
} }
if (thisthing.position || thisthing.parent_id) { if (thisthing.position || thisthing.parent_id) {
build.push(thisthing); build.push(thisthing);
@ -466,6 +486,8 @@ class Channel {
}); });
div.addEventListener("drop", (event) => { div.addEventListener("drop", (event) => {
const that = Channel.dragged[0]; const that = Channel.dragged[0];
if (!that)
return;
event.preventDefault(); event.preventDefault();
if (container) { if (container) {
that.move_id = this.snowflake; that.move_id = this.snowflake;
@ -506,7 +528,9 @@ class Channel {
} }
this.guild.headchannels = build; this.guild.headchannels = build;
} }
div.after(Channel.dragged[1]); if (Channel.dragged[1]) {
div.after(Channel.dragged[1]);
}
} }
this.guild.calculateReorder(); this.guild.calculateReorder();
}); });
@ -580,7 +604,9 @@ class Channel {
span.textContent = "Replying to " + this.replyingto.author.username; span.textContent = "Replying to " + this.replyingto.author.username;
const X = document.createElement("button"); const X = document.createElement("button");
X.onclick = _ => { X.onclick = _ => {
this.replyingto.div.classList.remove("replying"); if (this.replyingto) {
this.replyingto.div.classList.remove("replying");
}
replybox.classList.add("hideReplyBox"); replybox.classList.add("hideReplyBox");
this.replyingto = null; this.replyingto = null;
replybox.innerHTML = ""; replybox.innerHTML = "";
@ -618,11 +644,13 @@ class Channel {
if (this.localuser.channelfocus && this.localuser.channelfocus.myhtml) { if (this.localuser.channelfocus && this.localuser.channelfocus.myhtml) {
this.localuser.channelfocus.myhtml.classList.remove("viewChannel"); this.localuser.channelfocus.myhtml.classList.remove("viewChannel");
} }
this.myhtml.classList.add("viewChannel"); if (this.myhtml) {
this.myhtml.classList.add("viewChannel");
}
this.guild.prevchannel = this; this.guild.prevchannel = this;
this.localuser.channelfocus = this; this.localuser.channelfocus = this;
const prom = this.infinite.delete(); const prom = this.infinite.delete();
history.pushState(null, null, "/channels/" + this.guild_id + "/" + this.snowflake); history.pushState(null, "", "/channels/" + this.guild_id + "/" + this.snowflake);
document.getElementById("channelname").textContent = "#" + this.name; document.getElementById("channelname").textContent = "#" + this.name;
const loading = document.getElementById("loadingdiv"); const loading = document.getElementById("loadingdiv");
Channel.regenLoadingMessages(); Channel.regenLoadingMessages();
@ -782,7 +810,9 @@ class Channel {
} }
buildmessage(message, next) { buildmessage(message, next) {
const built = message.buildhtml(next); const built = message.buildhtml(next);
document.getElementById("messages").prepend(built); if (built) {
document.getElementById("messages").prepend(built);
}
} }
async buildmessages() { async buildmessages() {
/* /*
@ -809,7 +839,7 @@ class Channel {
if (this.lastreadmessageid && this.lastreadmessageid.getObject()) { if (this.lastreadmessageid && this.lastreadmessageid.getObject()) {
id = this.lastreadmessageid; id = this.lastreadmessageid;
} }
else if (id = this.findClosest(this.lastreadmessageid)) { else if (this.lastreadmessageid && (id = this.findClosest(this.lastreadmessageid))) {
} }
else if (this.lastmessage && this.lastmessage.snowflake) { else if (this.lastmessage && this.lastmessage.snowflake) {
id = this.goBackIds(this.lastmessage.snowflake, 50); id = this.goBackIds(this.lastmessage.snowflake, 50);
@ -878,7 +908,7 @@ class Channel {
updateChannel(json) { updateChannel(json) {
this.type = json.type; this.type = json.type;
this.name = json.name; this.name = json.name;
this.parent_id = new SnowFlake(json.parent_id, undefined); this.parent_id = SnowFlake.getSnowFlakeFromID(json.parent_id, Channel);
this.parent = null; this.parent = null;
this.children = []; this.children = [];
this.guild_id = json.guild_id; this.guild_id = json.guild_id;
@ -890,7 +920,10 @@ class Channel {
} }
; ;
this.permission_overwrites.set(thing.id, new Permissions(thing.allow, thing.deny)); this.permission_overwrites.set(thing.id, new Permissions(thing.allow, thing.deny));
this.permission_overwritesar.push([SnowFlake.getSnowFlakeFromID(thing.id, Role), this.permission_overwrites.get(thing.id)]); const permisions = this.permission_overwrites.get(thing.id);
if (permisions) {
this.permission_overwritesar.push([SnowFlake.getSnowFlakeFromID(thing.id, Role), permisions]);
}
} }
this.topic = json.topic; this.topic = json.topic;
this.nsfw = json.nsfw; this.nsfw = json.nsfw;
@ -1001,7 +1034,7 @@ class Channel {
if (messagez.author === this.localuser.user) { if (messagez.author === this.localuser.user) {
return; return;
} }
if (this.localuser.lookingguild.prevchannel === this && document.hasFocus()) { if (this.localuser.lookingguild?.prevchannel === this && document.hasFocus()) {
return; return;
} }
if (this.notification === "all") { if (this.notification === "all") {
@ -1069,18 +1102,20 @@ class Channel {
} }
async updateRolePermissions(id, perms) { async updateRolePermissions(id, perms) {
const permission = this.permission_overwrites.get(id); const permission = this.permission_overwrites.get(id);
permission.allow = perms.allow; if (permission) {
permission.deny = perms.deny; permission.allow = perms.allow;
await fetch(this.info.api + "/channels/" + this.snowflake + "/permissions/" + id, { permission.deny = perms.deny;
method: "PUT", await fetch(this.info.api + "/channels/" + this.snowflake + "/permissions/" + id, {
headers: this.headers, method: "PUT",
body: JSON.stringify({ headers: this.headers,
allow: permission.allow.toString(), body: JSON.stringify({
deny: permission.deny.toString(), allow: permission.allow.toString(),
id: id, deny: permission.deny.toString(),
type: 0 id: id,
}) type: 0
}); })
});
}
} }
} }
Channel.setupcontextmenu(); Channel.setupcontextmenu();

View file

@ -102,7 +102,7 @@ class Group extends Channel {
this.messageids = new Map(); this.messageids = new Map();
this.permission_overwrites = new Map(); this.permission_overwrites = new Map();
this.lastmessageid = SnowFlake.getSnowFlakeFromID(json.last_message_id, Message); this.lastmessageid = SnowFlake.getSnowFlakeFromID(json.last_message_id, Message);
this.lastmessageid ??= new SnowFlake("0", undefined); this.lastmessageid ??= null;
this.mentions = 0; this.mentions = 0;
this.setUpInfiniteScroller(); this.setUpInfiniteScroller();
this.position = Math.max(this.lastmessageid.getUnixTime(), this.snowflake.getUnixTime()); this.position = Math.max(this.lastmessageid.getUnixTime(), this.snowflake.getUnixTime());

View file

@ -74,7 +74,7 @@ class Guild {
settings.show(); settings.show();
} }
constructor(json, owner, member) { constructor(json, owner, member) {
if (json === -1) { if (json === -1 || member === null) {
return; return;
} }
if (json.stickers.length) { if (json.stickers.length) {
@ -109,7 +109,9 @@ class Guild {
} }
this.headchannels = []; this.headchannels = [];
for (const thing of this.channels) { for (const thing of this.channels) {
if (thing.resolveparent(this)) { const parent = thing.resolveparent(this);
console.log(parent, ":3");
if (!parent) {
this.headchannels.push(thing); this.headchannels.push(thing);
} }
} }
@ -347,11 +349,13 @@ class Guild {
} }
} }
getHTML() { getHTML() {
console.log("found :3", this.headchannels);
//this.printServers(); //this.printServers();
this.sortchannels(); this.sortchannels();
this.printServers(); this.printServers();
const build = document.createElement("div"); const build = document.createElement("div");
for (const thing of this.headchannels) { for (const thing of this.headchannels) {
console.log("found :3");
build.appendChild(thing.createguildHTML(this.isAdmin())); build.appendChild(thing.createguildHTML(this.isAdmin()));
} }
return build; return build;

View file

@ -19,7 +19,6 @@ class Localuser {
initialized; initialized;
info; info;
headers; headers;
usersettings;
userConnections; userConnections;
devPortal; devPortal;
ready; ready;
@ -47,7 +46,6 @@ class Localuser {
this.headers = { "Content-type": "application/json; charset=UTF-8", Authorization: this.userinfo.token }; this.headers = { "Content-type": "application/json; charset=UTF-8", Authorization: this.userinfo.token };
} }
gottenReady(ready) { gottenReady(ready) {
this.usersettings = null;
this.initialized = true; this.initialized = true;
this.ready = ready; this.ready = ready;
this.guilds = []; this.guilds = [];
@ -93,8 +91,10 @@ class Localuser {
} }
} }
outoffocus() { outoffocus() {
document.getElementById("servers").innerHTML = ""; const servers = document.getElementById("servers");
document.getElementById("channels").innerHTML = ""; servers.innerHTML = "";
const channels = document.getElementById("channels");
channels.innerHTML = "";
if (this.channelfocus) { if (this.channelfocus) {
this.channelfocus.infinite.delete(); this.channelfocus.infinite.delete();
} }
@ -114,32 +114,10 @@ class Localuser {
} }
swapped = false; swapped = false;
async initwebsocket() { async initwebsocket() {
let returny = null; let returny;
const promise = new Promise((res) => { returny = res; }); const ws = new WebSocket(this.serverurls.gateway.toString() + "?encoding=json&v=9" + (DecompressionStream ? "&compress=zlib-stream" : ""));
this.ws = new WebSocket(this.serverurls.gateway.toString() + "?encoding=json&v=9" + (DecompressionStream ? "&compress=zlib-stream" : "")); ;
this.ws.addEventListener('open', (_event) => { this.ws = ws;
console.log('WebSocket connected');
this.ws.send(JSON.stringify({
"op": 2,
"d": {
"token": this.token,
"capabilities": 16381,
"properties": {
"browser": "Jank Client",
"client_build_number": 0, //might update this eventually lol
"release_channel": "Custom",
"browser_user_agent": navigator.userAgent
},
"compress": !!DecompressionStream,
"presence": {
"status": "online",
"since": null, //new Date().getTime()
"activities": [],
"afk": false
}
}
}));
});
let ds; let ds;
let w; let w;
let r; let r;
@ -150,63 +128,91 @@ class Localuser {
w = ds.writable.getWriter(); w = ds.writable.getWriter();
r = ds.readable.getReader(); r = ds.readable.getReader();
arr = new Uint8Array(); arr = new Uint8Array();
const textdecode = new TextDecoder();
(async () => {
while (true) {
const read = await r.read();
const data = textdecode.decode(read.value);
build += data;
try {
const temp = JSON.parse(build);
build = "";
if (temp.op === 0 && temp.t === "READY") {
returny();
}
await this.handleEvent(temp);
}
catch { }
}
})();
} }
let order = new Promise((res) => (res())); const promise = new Promise((res) => {
this.ws.addEventListener('message', async (event) => { returny = res;
const temp2 = order; ws.addEventListener('open', (_event) => {
let res; console.log('WebSocket connected');
order = new Promise((r) => (res = r)); ws.send(JSON.stringify({
await temp2; "op": 2,
let temp; "d": {
try { "token": this.token,
if (event.data instanceof Blob) { "capabilities": 16381,
const buff = await event.data.arrayBuffer(); "properties": {
const array = new Uint8Array(buff); "browser": "Jank Client",
const temparr = new Uint8Array(array.length + arr.length); "client_build_number": 0, //might update this eventually lol
temparr.set(arr, 0); "release_channel": "Custom",
temparr.set(array, arr.length); "browser_user_agent": navigator.userAgent
arr = temparr; },
const len = array.length; "compress": !!DecompressionStream,
if (!(array[len - 1] === 255 && array[len - 2] === 255 && array[len - 3] === 0 && array[len - 4] === 0)) { "presence": {
return; "status": "online",
"since": null, //new Date().getTime()
"activities": [],
"afk": false
}
} }
w.write(arr.buffer); }));
arr = new Uint8Array(); });
return; //had to move the while loop due to me being dumb const textdecode = new TextDecoder();
} if (DecompressionStream) {
else { (async () => {
temp = JSON.parse(event.data); while (true) {
} const read = await r.read();
if (temp.op === 0 && temp.t === "READY") { const data = textdecode.decode(read.value);
returny(); build += data;
} try {
await this.handleEvent(temp); const temp = JSON.parse(build);
} build = "";
catch (e) { if (temp.op === 0 && temp.t === "READY") {
console.error(e); returny();
} }
finally { await this.handleEvent(temp);
res(); }
catch { }
}
})();
} }
}); });
this.ws.addEventListener("close", async (event) => { let order = new Promise((res) => (res()));
ws.addEventListener('message', async (event) => {
const temp2 = order;
order = new Promise(async (res) => {
await temp2;
let temp;
try {
if (event.data instanceof Blob) {
const buff = await event.data.arrayBuffer();
const array = new Uint8Array(buff);
const temparr = new Uint8Array(array.length + arr.length);
temparr.set(arr, 0);
temparr.set(array, arr.length);
arr = temparr;
const len = array.length;
if (!(array[len - 1] === 255 && array[len - 2] === 255 && array[len - 3] === 0 && array[len - 4] === 0)) {
return;
}
w.write(arr.buffer);
arr = new Uint8Array();
return; //had to move the while loop due to me being dumb
}
else {
temp = JSON.parse(event.data);
}
if (temp.op === 0 && temp.t === "READY") {
returny();
}
await this.handleEvent(temp);
}
catch (e) {
console.error(e);
}
finally {
res();
}
});
});
ws.addEventListener("close", async (event) => {
this.ws = undefined; this.ws = undefined;
console.log("WebSocket closed with code " + event.code); console.log("WebSocket closed with code " + event.code);
this.unload(); this.unload();
@ -264,8 +270,9 @@ class Localuser {
this.initwebsocket().then(() => { this.initwebsocket().then(() => {
this.loaduser(); this.loaduser();
this.init(); this.init();
document.getElementById("loading").classList.add("doneloading"); const loading = document.getElementById("loading");
document.getElementById("loading").classList.remove("loading"); loading.classList.add("doneloading");
loading.classList.remove("loading");
console.log("done loading"); console.log("done loading");
}); });
}, 200 + (this.errorBackoff * 2800)); }, 200 + (this.errorBackoff * 2800));
@ -330,9 +337,11 @@ class Localuser {
case "GUILD_DELETE": case "GUILD_DELETE":
{ {
const guildy = this.guildids.get(temp.d.id); const guildy = this.guildids.get(temp.d.id);
this.guildids.delete(temp.d.id); if (guildy) {
this.guilds.splice(this.guilds.indexOf(guildy), 1); this.guildids.delete(temp.d.id);
guildy.html.remove(); this.guilds.splice(this.guilds.indexOf(guildy), 1);
guildy.html.remove();
}
break; break;
} }
case "GUILD_CREATE": case "GUILD_CREATE":
@ -371,6 +380,8 @@ class Localuser {
} }
} }
else if (temp.op === 10) { else if (temp.op === 10) {
if (!this.ws)
return;
console.log("heartbeat down"); console.log("heartbeat down");
this.heartbeat_interval = temp.d.heartbeat_interval; this.heartbeat_interval = temp.d.heartbeat_interval;
this.ws.send(JSON.stringify({ op: 1, d: this.lastSequence })); this.ws.send(JSON.stringify({ op: 1, d: this.lastSequence }));
@ -395,21 +406,25 @@ class Localuser {
} }
updateChannel(json) { updateChannel(json) {
SnowFlake.getSnowFlakeFromID(json.guild_id, Guild).getObject().updateChannel(json); SnowFlake.getSnowFlakeFromID(json.guild_id, Guild).getObject().updateChannel(json);
if (json.guild_id === this.lookingguild.id) { if (json.guild_id === this.lookingguild?.id) {
this.loadGuild(json.guild_id); this.loadGuild(json.guild_id);
} }
} }
createChannel(json) { createChannel(json) {
json.guild_id ??= "@me"; json.guild_id ??= "@me";
SnowFlake.getSnowFlakeFromID(json.guild_id, Guild).getObject().createChannelpac(json); SnowFlake.getSnowFlakeFromID(json.guild_id, Guild).getObject().createChannelpac(json);
if (json.guild_id === this.lookingguild.id) { if (json.guild_id === this.lookingguild?.id) {
this.loadGuild(json.guild_id); this.loadGuild(json.guild_id);
} }
} }
delChannel(json) { delChannel(json) {
json.guild_id ??= "@me"; let guild_id = json.guild_id;
this.guildids.get(json.guild_id).delChannel(json); guild_id ??= "@me";
if (json.guild_id === this.lookingguild.id) { const guild = this.guildids.get(guild_id);
if (guild) {
guild.delChannel(json);
}
if (json.guild_id === this.lookingguild?.id) {
this.loadGuild(json.guild_id); this.loadGuild(json.guild_id);
} }
} }
@ -418,6 +433,9 @@ class Localuser {
this.buildservers(); this.buildservers();
if (location[3] === "channels") { if (location[3] === "channels") {
const guild = this.loadGuild(location[4]); const guild = this.loadGuild(location[4]);
if (!guild) {
return;
}
guild.loadChannel(location[5]); guild.loadChannel(location[5]);
this.channelfocus = guild.channelids[location[5]]; this.channelfocus = guild.channelids[location[5]];
} }
@ -428,7 +446,12 @@ class Localuser {
document.getElementById("status").textContent = this.status; document.getElementById("status").textContent = this.status;
} }
isAdmin() { isAdmin() {
return this.lookingguild.isAdmin(); if (this.lookingguild) {
return this.lookingguild.isAdmin();
}
else {
return false;
}
} }
loadGuild(id) { loadGuild(id) {
let guild = this.guildids.get(id); let guild = this.guildids.get(id);
@ -438,14 +461,19 @@ class Localuser {
if (this.lookingguild) { if (this.lookingguild) {
this.lookingguild.html.classList.remove("serveropen"); this.lookingguild.html.classList.remove("serveropen");
} }
if (!guild)
return;
if (guild.html) { if (guild.html) {
guild.html.classList.add("serveropen"); guild.html.classList.add("serveropen");
} }
this.lookingguild = guild; this.lookingguild = guild;
document.getElementById("serverName").textContent = guild.properties.name; document.getElementById("serverName").textContent = guild.properties.name;
//console.log(this.guildids,id) //console.log(this.guildids,id)
document.getElementById("channels").innerHTML = ""; const channels = document.getElementById("channels");
document.getElementById("channels").appendChild(guild.getHTML()); channels.innerHTML = "";
const html = guild.getHTML();
channels.appendChild(html);
console.log("found :3", html);
return guild; return guild;
} }
buildservers() { buildservers() {
@ -553,8 +581,10 @@ class Localuser {
["vdiv", ["vdiv",
["title", "Create a guild"], ["title", "Create a guild"],
["fileupload", "Icon:", function (event) { ["fileupload", "Icon:", function (event) {
const reader = new FileReader();
const target = event.target; const target = event.target;
if (!target.files)
return;
const reader = new FileReader();
reader.readAsDataURL(target.files[0]); reader.readAsDataURL(target.files[0]);
reader.onload = () => { reader.onload = () => {
fields.icon = reader.result; fields.icon = reader.result;
@ -640,7 +670,10 @@ class Localuser {
} }
messageCreate(messagep) { messageCreate(messagep) {
messagep.d.guild_id ??= "@me"; messagep.d.guild_id ??= "@me";
this.guildids.get(messagep.d.guild_id).channelids[messagep.d.channel_id].messageCreate(messagep); const guild = this.guildids.get(messagep.d.guild_id);
if (!guild)
return;
guild.channelids[messagep.d.channel_id].messageCreate(messagep);
this.unreads(); this.unreads();
} }
unreads() { unreads() {
@ -653,8 +686,10 @@ class Localuser {
} }
} }
async typingStart(typing) { async typingStart(typing) {
if (this.channelfocus.id === typing.d.channel_id) { if (this.channelfocus?.id === typing.d.channel_id) {
const guild = this.guildids.get(typing.d.guild_id); const guild = this.guildids.get(typing.d.guild_id);
if (!guild)
return;
const memb = await Member.new(typing.d.member, guild); const memb = await Member.new(typing.d.member, guild);
if (memb.id === this.user.id) { if (memb.id === this.user.id) {
console.log("you is typing"); console.log("you is typing");
@ -742,7 +777,8 @@ class Localuser {
} }
if (showing) { if (showing) {
typingtext.classList.remove("hidden"); typingtext.classList.remove("hidden");
document.getElementById("typingtext").textContent = build; const typingtext2 = document.getElementById("typingtext");
typingtext2.textContent = build;
} }
else { else {
typingtext.classList.add("hidden"); typingtext.classList.add("hidden");
@ -750,7 +786,6 @@ class Localuser {
} }
showusersettings() { showusersettings() {
const settings = new Settings("Settings"); const settings = new Settings("Settings");
this.usersettings = settings;
{ {
const userOptions = settings.addButton("User Settings", { ltr: true }); const userOptions = settings.addButton("User Settings", { ltr: true });
const hypotheticalProfile = document.createElement("div"); const hypotheticalProfile = document.createElement("div");
@ -1184,15 +1219,15 @@ class Localuser {
if (guildid === "@me") { if (guildid === "@me") {
return undefined; return undefined;
} }
if (!this.waitingmembers.has(guildid)) { let guildmap = this.waitingmembers.get(guildid);
this.waitingmembers.set(guildid, new Map()); if (!guildmap) {
guildmap = new Map();
this.waitingmembers.set(guildid, guildmap);
} }
let res; const promise = new Promise((res) => {
const promise = new Promise((r) => { guildmap.set(id, res);
res = r; this.getmembers();
}); });
this.waitingmembers.get(guildid).set(id, res);
this.getmembers();
return await promise; return await promise;
} }
fetchingmembers = new Map(); fetchingmembers = new Map();
@ -1200,11 +1235,15 @@ class Localuser {
noncebuild = new Map(); noncebuild = new Map();
async gotChunk(chunk) { async gotChunk(chunk) {
for (const thing of chunk.presences) { for (const thing of chunk.presences) {
this.presences.set(thing.user.id, thing); if (thing.user) {
this.presences.set(thing.user.id, thing);
}
} }
console.log(chunk); console.log(chunk);
chunk.members ??= []; chunk.members ??= [];
const arr = this.noncebuild.get(chunk.nonce); const arr = this.noncebuild.get(chunk.nonce);
if (!arr)
return;
arr[0] = arr[0].concat(chunk.members); arr[0] = arr[0].concat(chunk.members);
if (chunk.not_found) { if (chunk.not_found) {
arr[1] = chunk.not_found; arr[1] = chunk.not_found;
@ -1214,14 +1253,14 @@ class Localuser {
console.log("got through"); console.log("got through");
this.noncebuild.delete(chunk.nonce); this.noncebuild.delete(chunk.nonce);
const func = this.noncemap.get(chunk.nonce); const func = this.noncemap.get(chunk.nonce);
if (!func)
return;
func([arr[0], arr[1]]); func([arr[0], arr[1]]);
this.noncemap.delete(chunk.nonce); this.noncemap.delete(chunk.nonce);
} }
} }
async getmembers() { async getmembers() {
let res; const promise = new Promise(res => { setTimeout(res, 10); });
const promise = new Promise(r => res = r);
setTimeout(res, 10);
await promise; //allow for more to be sent at once :P await promise; //allow for more to be sent at once :P
if (this.ws) { if (this.ws) {
this.waitingmembers.forEach(async (value, guildid) => { this.waitingmembers.forEach(async (value, guildid) => {
@ -1242,36 +1281,42 @@ class Localuser {
return; return;
} }
; ;
let res; const promise = new Promise((res) => {
const promise = new Promise((r) => { const nonce = "" + Math.floor(Math.random() * 100000000000);
res = r; this.noncemap.set(nonce, res);
this.noncebuild.set(nonce, [[], [], []]);
if (!this.ws)
return;
this.ws.send(JSON.stringify({
op: 8,
d: {
user_ids: build,
guild_id: guildid,
limit: 100,
nonce,
presences: true
}
}));
this.fetchingmembers.set(guildid, true);
}); });
const nonce = "" + Math.floor(Math.random() * 100000000000);
this.noncemap.set(nonce, res);
this.noncebuild.set(nonce, [[], [], []]);
this.ws.send(JSON.stringify({
op: 8,
d: {
user_ids: build,
guild_id: guildid,
limit: 100,
nonce,
presences: true
}
}));
this.fetchingmembers.set(guildid, true);
const prom = await promise; const prom = await promise;
; ;
const data = prom[0]; const data = prom[0];
for (const thing of data) { for (const thing of data) {
if (value.has(thing.id)) { if (value.has(thing.id)) {
value.get(thing.id)(thing); const func = value.get(thing.id);
if (!func)
continue;
func(thing);
value.delete(thing.id); value.delete(thing.id);
} }
} }
for (const thing of prom[1]) { for (const thing of prom[1]) {
if (value.has(thing)) { if (value.has(thing)) {
value.get(thing)(undefined); const func = value.get(thing);
if (!func)
continue;
func(undefined);
value.delete(thing); value.delete(thing);
} }
} }
@ -1320,7 +1365,7 @@ let fixsvgtheme;
else if (g === max) { else if (g === max) {
h = 2 + (b - r) / (max - min); h = 2 + (b - r) / (max - min);
} }
else if (b === max) { else {
h = 4 + (r - g) / (max - min); h = 4 + (r - g) / (max - min);
} }
} }

View file

@ -7,7 +7,9 @@
"esModuleInterop": true, "esModuleInterop": true,
"outDir": "./.dist", "outDir": "./.dist",
"removeComments": false, "removeComments": false,
"noImplicitThis":true "noImplicitThis":true,
"useUnknownInCatchVariables":true,
"strictNullChecks":true
}, },
"include": [ "include": [
"./webpage/*.ts" "./webpage/*.ts"

View file

@ -78,6 +78,7 @@ class Voice{
return 0; return 0;
} }
} }
return new Function();
} }
play():void{ play():void{
if(this.playing){ if(this.playing){

View file

@ -14,7 +14,7 @@ import { channeljson, messagejson, readyjson } from "./jsontypes.js";
declare global { declare global {
interface NotificationOptions { interface NotificationOptions {
image?: string image?: string|null|undefined
} }
} }
class Channel{ class Channel{
@ -24,8 +24,8 @@ class Channel{
headers:Localuser["headers"]; headers:Localuser["headers"];
name:string; name:string;
snowflake:SnowFlake<Channel>; snowflake:SnowFlake<Channel>;
parent_id:SnowFlake<Channel>; parent_id:SnowFlake<Channel>|null;
parent:Channel; parent:Channel|null;
children:Channel[]; children:Channel[];
guild_id:string; guild_id:string;
messageids:Map<SnowFlake<Message>,Message>; messageids:Map<SnowFlake<Message>,Message>;
@ -34,19 +34,19 @@ class Channel{
topic:string; topic:string;
nsfw:boolean; nsfw:boolean;
position:number; position:number;
lastreadmessageid:SnowFlake<Message>; lastreadmessageid:SnowFlake<Message>|null;
lastmessageid:SnowFlake<Message>; lastmessageid:SnowFlake<Message>|null;
mentions:number; mentions:number;
lastpin:string; lastpin:string;
move_id:SnowFlake<Channel>; move_id:SnowFlake<Channel>|null;
typing:number; typing:number;
message_notifications:number; message_notifications:number;
allthewayup:boolean; allthewayup:boolean;
static contextmenu=new Contextmenu("channel menu"); static contextmenu=new Contextmenu("channel menu");
replyingto:Message; replyingto:Message|null;
infinite:InfiniteScroller; infinite:InfiniteScroller;
idToPrev:Map<SnowFlake<Message>,SnowFlake<Message>>=new Map(); idToPrev:Map<SnowFlake<Message>,SnowFlake<Message>|null>=new Map();
idToNext:Map<SnowFlake<Message>,SnowFlake<Message>>=new Map(); idToNext:Map<SnowFlake<Message>,SnowFlake<Message>|null>=new Map();
get id(){ get id(){
return this.snowflake.id; return this.snowflake.id;
} }
@ -112,7 +112,9 @@ class Channel{
copy.classList.add("copybutton","svgtheme"); copy.classList.add("copybutton","svgtheme");
copycontainer.append(copy); copycontainer.append(copy);
copycontainer.onclick=_=>{ copycontainer.onclick=_=>{
navigator.clipboard.writeText(text.textContent); if(text.textContent){
navigator.clipboard.writeText(text.textContent);
}
} }
div.append(copycontainer); div.append(copycontainer);
const update=()=>{ const update=()=>{
@ -165,7 +167,7 @@ class Channel{
}) })
} }
setUpInfiniteScroller(){ setUpInfiniteScroller(){
this.infinite=new InfiniteScroller(async function(this:Channel,id:string,offset:number):Promise<string>{ this.infinite=new InfiniteScroller(async function(this:Channel,id:string,offset:number):Promise<string|undefined>{
const snowflake=SnowFlake.getSnowFlakeFromID(id,Message) as SnowFlake<Message>; const snowflake=SnowFlake.getSnowFlakeFromID(id,Message) as SnowFlake<Message>;
if(offset===1){ if(offset===1){
if(this.idToPrev.has(snowflake)){ if(this.idToPrev.has(snowflake)){
@ -193,8 +195,15 @@ class Channel{
console.error("Uh...") console.error("Uh...")
} }
try{ try{
const html=snowflake.getObject().buildhtml(this.messageids.get(this.idToPrev.get(snowflake))); const prev=this.idToPrev.get(snowflake);
return html; if(prev){
const messgage=this.messageids.get(prev);
if(messgage){
const html=snowflake.getObject().buildhtml(messgage);
return html;
}
}
}catch(e){ }catch(e){
console.error(e); console.error(e);
} }
@ -221,7 +230,9 @@ class Channel{
this.headers=this.owner.headers; this.headers=this.owner.headers;
this.name=json.name; this.name=json.name;
this.snowflake=new SnowFlake(json.id,this); this.snowflake=new SnowFlake(json.id,this);
this.parent_id=new SnowFlake(json.parent_id,undefined); if(json.parent_id){
this.parent_id=SnowFlake.getSnowFlakeFromID(json.parent_id,Channel);
}
this.parent=null; this.parent=null;
this.children=[]; this.children=[];
this.guild_id=json.guild_id; this.guild_id=json.guild_id;
@ -231,7 +242,10 @@ class Channel{
for(const thing of json.permission_overwrites){ for(const thing of json.permission_overwrites){
if(thing.id==="1182819038095799904"||thing.id==="1182820803700625444"){continue;}; if(thing.id==="1182819038095799904"||thing.id==="1182820803700625444"){continue;};
this.permission_overwrites.set(thing.id,new Permissions(thing.allow,thing.deny)); this.permission_overwrites.set(thing.id,new Permissions(thing.allow,thing.deny));
this.permission_overwritesar.push([SnowFlake.getSnowFlakeFromID(thing.id,Role),this.permission_overwrites.get(thing.id)]); const permission=this.permission_overwrites.get(thing.id);
if(permission){
this.permission_overwritesar.push([SnowFlake.getSnowFlakeFromID(thing.id,Role),permission]);
}
} }
this.topic=json.topic; this.topic=json.topic;
@ -261,15 +275,16 @@ class Channel{
} }
get hasunreads():boolean{ get hasunreads():boolean{
if(!this.hasPermission("VIEW_CHANNEL")){return false;} if(!this.hasPermission("VIEW_CHANNEL")){return false;}
return this.lastmessageid!==this.lastreadmessageid&&this.type!==4&&!!this.lastmessageid.id; return this.lastmessageid!==this.lastreadmessageid&&this.type!==4&&!!this.lastmessageid;
} }
hasPermission(name:string,member=this.guild.member):boolean{ hasPermission(name:string,member=this.guild.member):boolean{
if(member.isAdmin()){ if(member.isAdmin()){
return true; return true;
} }
for(const thing of member.roles){ for(const thing of member.roles){
if(this.permission_overwrites.get(thing.id)){ const premission=this.permission_overwrites.get(thing.id);
let perm=this.permission_overwrites.get(thing.id).getPermission(name); if(premission){
let perm=premission.getPermission(name);
if(perm){ if(perm){
return perm===1; return perm===1;
} }
@ -282,7 +297,10 @@ class Channel{
} }
get canMessage():boolean{ get canMessage():boolean{
if((0===this.permission_overwritesar.length)&&this.hasPermission("MANAGE_CHANNELS")){ if((0===this.permission_overwritesar.length)&&this.hasPermission("MANAGE_CHANNELS")){
this.addRoleToPerms(this.guild.roles.find(_=>_.name==="@everyone")); const role=this.guild.roles.find(_=>_.name==="@everyone");
if(role){
this.addRoleToPerms(role);
}
} }
return this.hasPermission("SEND_MESSAGES"); return this.hasPermission("SEND_MESSAGES");
} }
@ -290,18 +308,20 @@ class Channel{
this.children.sort((a,b)=>{return a.position-b.position}); this.children.sort((a,b)=>{return a.position-b.position});
} }
resolveparent(guild:Guild){ resolveparent(guild:Guild){
this.parent=guild.channelids[this.parent_id?.id]; const parentid=this.parent_id?.id;
if(!parentid) return false;
this.parent=guild.channelids[parentid];
this.parent??=null; this.parent??=null;
if(this.parent!==null){ if(this.parent!==null){
this.parent.children.push(this); this.parent.children.push(this);
} }
return this.parent===null; return this.parent!==null;
} }
calculateReorder(){ calculateReorder(){
let position=-1; let position=-1;
let build=[]; let build:{id:SnowFlake<Channel>,position:number|undefined,parent_id:SnowFlake<Channel>|undefined}[]=[];
for(const thing of this.children){ for(const thing of this.children){
const thisthing={id:thing.snowflake,position:undefined,parent_id:undefined}; const thisthing:{id:SnowFlake<Channel>,position:number|undefined,parent_id:SnowFlake<Channel>|undefined}={id:thing.snowflake,position:undefined,parent_id:undefined};
if(thing.position<position){ if(thing.position<position){
thing.position=thisthing.position=position+1; thing.position=thisthing.position=position+1;
} }
@ -309,8 +329,8 @@ class Channel{
if(thing.move_id&&thing.move_id!==thing.parent_id){ if(thing.move_id&&thing.move_id!==thing.parent_id){
thing.parent_id=thing.move_id; thing.parent_id=thing.move_id;
thisthing.parent_id=thing.parent_id; thisthing.parent_id=thing.parent_id;
thing.move_id=undefined; thing.move_id=null;
console.log(this.guild.channelids[thisthing.parent_id]); console.log(this.guild.channelids[thisthing.parent_id.id]);
} }
if(thisthing.position||thisthing.parent_id){ if(thisthing.position||thisthing.parent_id){
build.push(thisthing); build.push(thisthing);
@ -318,7 +338,7 @@ class Channel{
} }
return build; return build;
} }
static dragged=[]; static dragged:[Channel,HTMLDivElement]|[]=[];
createguildHTML(admin=false):HTMLDivElement{ createguildHTML(admin=false):HTMLDivElement{
const div=document.createElement("div"); const div=document.createElement("div");
if(!this.hasPermission("VIEW_CHANNEL")){ if(!this.hasPermission("VIEW_CHANNEL")){
@ -423,7 +443,7 @@ class Channel{
return div; return div;
} }
get myhtml(){ get myhtml(){
const search=document.getElementById("channels").children[0].children const search=(document.getElementById("channels") as HTMLDivElement).children[0].children
if(this.guild!==this.localuser.lookingguild){ if(this.guild!==this.localuser.lookingguild){
return null return null
}else if(this.parent){ }else if(this.parent){
@ -472,6 +492,7 @@ class Channel{
div.addEventListener("drop", (event) => { div.addEventListener("drop", (event) => {
const that=Channel.dragged[0]; const that=Channel.dragged[0];
if(!that) return;
event.preventDefault(); event.preventDefault();
if(container){ if(container){
that.move_id=this.snowflake; that.move_id=this.snowflake;
@ -479,7 +500,7 @@ class Channel{
that.parent.children.splice(that.parent.children.indexOf(that),1); that.parent.children.splice(that.parent.children.indexOf(that),1);
} }
that.parent=this; that.parent=this;
(container as HTMLElement).prepend(Channel.dragged[1]); (container as HTMLElement).prepend(Channel.dragged[1] as HTMLDivElement);
this.children.unshift(that); this.children.unshift(that);
}else{ }else{
console.log(this,Channel.dragged); console.log(this,Channel.dragged);
@ -491,7 +512,7 @@ class Channel{
} }
that.parent=this.parent; that.parent=this.parent;
if(that.parent){ if(that.parent){
const build=[]; const build:Channel[]=[];
for(let i=0;i<that.parent.children.length;i++){ for(let i=0;i<that.parent.children.length;i++){
build.push(that.parent.children[i]) build.push(that.parent.children[i])
if(that.parent.children[i]===this){ if(that.parent.children[i]===this){
@ -500,7 +521,7 @@ class Channel{
} }
that.parent.children=build; that.parent.children=build;
}else{ }else{
const build=[]; const build:Channel[]=[];
for(let i=0;i<this.guild.headchannels.length;i++){ for(let i=0;i<this.guild.headchannels.length;i++){
build.push(this.guild.headchannels[i]) build.push(this.guild.headchannels[i])
if(this.guild.headchannels[i]===this){ if(this.guild.headchannels[i]===this){
@ -509,7 +530,9 @@ class Channel{
} }
this.guild.headchannels=build; this.guild.headchannels=build;
} }
div.after(Channel.dragged[1]); if(Channel.dragged[1]){
div.after(Channel.dragged[1]);
}
} }
this.guild.calculateReorder() this.guild.calculateReorder()
}); });
@ -581,14 +604,16 @@ class Channel{
} }
makereplybox(){ makereplybox(){
const replybox=document.getElementById("replybox"); const replybox=document.getElementById("replybox") as HTMLElement;
if(this.replyingto){ if(this.replyingto){
replybox.innerHTML=""; replybox.innerHTML="";
const span=document.createElement("span"); const span=document.createElement("span");
span.textContent="Replying to "+this.replyingto.author.username; span.textContent="Replying to "+this.replyingto.author.username;
const X=document.createElement("button"); const X=document.createElement("button");
X.onclick=_=>{ X.onclick=_=>{
this.replyingto.div.classList.remove("replying"); if(this.replyingto){
this.replyingto.div.classList.remove("replying");
}
replybox.classList.add("hideReplyBox"); replybox.classList.add("hideReplyBox");
this.replyingto=null; this.replyingto=null;
replybox.innerHTML=""; replybox.innerHTML="";
@ -624,14 +649,15 @@ class Channel{
if(this.localuser.channelfocus&&this.localuser.channelfocus.myhtml){ if(this.localuser.channelfocus&&this.localuser.channelfocus.myhtml){
this.localuser.channelfocus.myhtml.classList.remove("viewChannel"); this.localuser.channelfocus.myhtml.classList.remove("viewChannel");
} }
this.myhtml.classList.add("viewChannel") if(this.myhtml){
this.myhtml.classList.add("viewChannel")
}
this.guild.prevchannel=this; this.guild.prevchannel=this;
this.localuser.channelfocus=this; this.localuser.channelfocus=this;
const prom=this.infinite.delete(); const prom=this.infinite.delete();
history.pushState(null, null,"/channels/"+this.guild_id+"/"+this.snowflake); history.pushState(null, "","/channels/"+this.guild_id+"/"+this.snowflake);
document.getElementById("channelname").textContent="#"+this.name; (document.getElementById("channelname") as HTMLSpanElement).textContent="#"+this.name;
const loading=document.getElementById("loadingdiv"); const loading=document.getElementById("loadingdiv") as HTMLDivElement;
Channel.regenLoadingMessages(); Channel.regenLoadingMessages();
loading.classList.add("loading"); loading.classList.add("loading");
await this.putmessages(); await this.putmessages();
@ -644,10 +670,10 @@ class Channel{
await this.buildmessages(); await this.buildmessages();
//loading.classList.remove("loading"); //loading.classList.remove("loading");
console.log(this); console.log(this);
document.getElementById("typebox").contentEditable=""+this.canMessage; (document.getElementById("typebox") as HTMLDivElement).contentEditable=""+this.canMessage;
} }
static regenLoadingMessages(){ static regenLoadingMessages(){
const loading=document.getElementById("loadingdiv"); const loading=document.getElementById("loadingdiv") as HTMLDivElement;
loading.innerHTML=""; loading.innerHTML="";
for(let i=0;i<15;i++){ for(let i=0;i<15;i++){
const div=document.createElement("div"); const div=document.createElement("div");
@ -682,7 +708,7 @@ class Channel{
if(response.length!==100){ if(response.length!==100){
this.allthewayup=true; this.allthewayup=true;
} }
let prev:Message=undefined; let prev:Message|undefined=undefined;
for(const thing of response){ for(const thing of response){
const message=new Message(thing,this); const message=new Message(thing,this);
if(prev){ if(prev){
@ -698,7 +724,7 @@ class Channel{
} }
} }
delChannel(json:channeljson){ delChannel(json:channeljson){
const build=[]; const build:Channel[]=[];
for(const thing of this.children){ for(const thing of this.children){
if(thing.id!==json.id){ if(thing.id!==json.id){
build.push(thing) build.push(thing)
@ -788,7 +814,9 @@ class Channel{
} }
buildmessage(message:Message,next:Message){ buildmessage(message:Message,next:Message){
const built=message.buildhtml(next); const built=message.buildhtml(next);
document.getElementById("messages").prepend(built); if(built){
(document.getElementById("messages") as HTMLDivElement).prepend(built);
}
} }
async buildmessages(){ async buildmessages(){
/* /*
@ -803,17 +831,17 @@ class Channel{
private async tryfocusinfinate(){ private async tryfocusinfinate(){
if(this.infinitefocus) return; if(this.infinitefocus) return;
this.infinitefocus=true; this.infinitefocus=true;
const messages=document.getElementById("channelw"); const messages=document.getElementById("channelw") as HTMLDivElement;
for(const thing of messages.getElementsByClassName("messagecontainer")){ for(const thing of messages.getElementsByClassName("messagecontainer")){
thing.remove(); thing.remove();
} }
const loading=document.getElementById("loadingdiv"); const loading=document.getElementById("loadingdiv") as HTMLDivElement;
const removetitle=document.getElementById("removetitle"); const removetitle=document.getElementById("removetitle");
//messages.innerHTML=""; //messages.innerHTML="";
let id:SnowFlake<Message>; let id:SnowFlake<Message>|undefined;
if(this.lastreadmessageid&&this.lastreadmessageid.getObject()){ if(this.lastreadmessageid&&this.lastreadmessageid.getObject()){
id=this.lastreadmessageid; id=this.lastreadmessageid;
}else if(id=this.findClosest(this.lastreadmessageid)){ }else if(this.lastreadmessageid&&(id=this.findClosest(this.lastreadmessageid))){
}else if(this.lastmessage&&this.lastmessage.snowflake){ }else if(this.lastmessage&&this.lastmessage.snowflake){
id=this.goBackIds(this.lastmessage.snowflake,50); id=this.goBackIds(this.lastmessage.snowflake,50);
@ -842,7 +870,7 @@ class Channel{
//this.infinite.focus(id.id,false); //this.infinite.focus(id.id,false);
} }
private goBackIds(id:SnowFlake<Message>,back:number,returnifnotexistant=true):SnowFlake<Message>{ private goBackIds(id:SnowFlake<Message>,back:number,returnifnotexistant=true):SnowFlake<Message>|undefined{
while(back!==0){ while(back!==0){
const nextid=this.idToPrev.get(id); const nextid=this.idToPrev.get(id);
if(nextid){ if(nextid){
@ -860,7 +888,7 @@ class Channel{
} }
private findClosest(snowflake:SnowFlake<Message>){ private findClosest(snowflake:SnowFlake<Message>){
if(!this.lastmessage) return; if(!this.lastmessage) return;
let flake=this.lastmessage.snowflake; let flake:SnowFlake<Message>|null|undefined=this.lastmessage.snowflake;
if(!snowflake){return}; if(!snowflake){return};
const time=snowflake.getUnixTime(); const time=snowflake.getUnixTime();
let flaketime=flake.getUnixTime() let flaketime=flake.getUnixTime()
@ -876,7 +904,7 @@ class Channel{
updateChannel(json:channeljson){ updateChannel(json:channeljson){
this.type=json.type; this.type=json.type;
this.name=json.name; this.name=json.name;
this.parent_id=new SnowFlake(json.parent_id,undefined); this.parent_id=SnowFlake.getSnowFlakeFromID(json.parent_id,Channel);
this.parent=null; this.parent=null;
this.children=[]; this.children=[];
this.guild_id=json.guild_id; this.guild_id=json.guild_id;
@ -885,7 +913,10 @@ class Channel{
for(const thing of json.permission_overwrites){ for(const thing of json.permission_overwrites){
if(thing.id==="1182819038095799904"||thing.id==="1182820803700625444"){continue;}; if(thing.id==="1182819038095799904"||thing.id==="1182820803700625444"){continue;};
this.permission_overwrites.set(thing.id,new Permissions(thing.allow,thing.deny)); this.permission_overwrites.set(thing.id,new Permissions(thing.allow,thing.deny));
this.permission_overwritesar.push([SnowFlake.getSnowFlakeFromID(thing.id,Role),this.permission_overwrites.get(thing.id)]); const permisions=this.permission_overwrites.get(thing.id);
if(permisions){
this.permission_overwritesar.push([SnowFlake.getSnowFlakeFromID(thing.id,Role),permisions]);
}
} }
this.topic=json.topic; this.topic=json.topic;
this.nsfw=json.nsfw; this.nsfw=json.nsfw;
@ -901,7 +932,7 @@ class Channel{
}) })
} }
get notification(){ get notification(){
let notinumber=this.message_notifications; let notinumber:number|null=this.message_notifications;
if(+notinumber===3){notinumber=null;} if(+notinumber===3){notinumber=null;}
notinumber??=this.guild.message_notifications; notinumber??=this.guild.message_notifications;
switch(+notinumber){ switch(+notinumber){
@ -915,7 +946,8 @@ class Channel{
return "default"; return "default";
} }
} }
async sendMessage(content:string,{attachments=[],embeds=[],replyingto=null}){ async sendMessage(content:string,{attachments=[],embeds=[],replyingto=null}:
{attachments,embeds,replyingto:Message|null}){
let replyjson:any; let replyjson:any;
if(replyingto){ if(replyingto){
replyjson= replyjson=
@ -988,7 +1020,7 @@ class Channel{
if(messagez.author===this.localuser.user){ if(messagez.author===this.localuser.user){
return; return;
} }
if(this.localuser.lookingguild.prevchannel===this&&document.hasFocus()){ if(this.localuser.lookingguild?.prevchannel===this&&document.hasFocus()){
return; return;
} }
if(this.notification==="all"){ if(this.notification==="all"){
@ -1006,13 +1038,13 @@ class Channel{
if (!("Notification" in window)) { if (!("Notification" in window)) {
} else if (Notification.permission === "granted") { } else if (Notification.permission === "granted") {
let noticontent=message.content.textContent; let noticontent:string|undefined|null=message.content.textContent;
if(message.embeds[0]){ if(message.embeds[0]){
noticontent||=message.embeds[0].json.title; noticontent||=message.embeds[0].json.title;
noticontent||=message.content.textContent; noticontent||=message.content.textContent;
} }
noticontent||="Blank Message"; noticontent||="Blank Message";
let imgurl=null; let imgurl:null|string=null;
const images=message.getimages(); const images=message.getimages();
if(images.length){ if(images.length){
const image = images[0]; const image = images[0];
@ -1052,18 +1084,20 @@ class Channel{
} }
async updateRolePermissions(id:string,perms:Permissions){ async updateRolePermissions(id:string,perms:Permissions){
const permission=this.permission_overwrites.get(id); const permission=this.permission_overwrites.get(id);
permission.allow=perms.allow; if(permission){
permission.deny=perms.deny; permission.allow=perms.allow;
await fetch(this.info.api+"/channels/"+this.snowflake+"/permissions/"+id,{ permission.deny=perms.deny;
method:"PUT", await fetch(this.info.api+"/channels/"+this.snowflake+"/permissions/"+id,{
headers:this.headers, method:"PUT",
body:JSON.stringify({ headers:this.headers,
allow:permission.allow.toString(), body:JSON.stringify({
deny:permission.deny.toString(), allow:permission.allow.toString(),
id:id, deny:permission.deny.toString(),
type:0 id:id,
type:0
})
}) })
}) }
} }
} }
Channel.setupcontextmenu(); Channel.setupcontextmenu();

View file

@ -1,7 +1,7 @@
class Contextmenu{ class Contextmenu{
static currentmenu; static currentmenu;
name:string; name:string;
buttons:[string,Function,string,Function,Function,string][]; buttons:[string,Function,string|null,Function,Function,string][];
div:HTMLDivElement; div:HTMLDivElement;
static setup(){ static setup(){
Contextmenu.currentmenu=""; Contextmenu.currentmenu="";
@ -19,8 +19,8 @@ class Contextmenu{
this.name=name; this.name=name;
this.buttons=[] this.buttons=[]
} }
addbutton(text:string,onclick:Function,img=null,shown=_=>true,enabled=_=>true){ addbutton(text:string,onclick:Function,img:null|string=null,shown=_=>true,enabled=_=>true){
this.buttons.push([text,onclick,img,shown,enabled,"button"]) this.buttons.push([text,onclick,img,shown,enabled,"button"]);
return {}; return {};
} }
addsubmenu(text:string,onclick:(e:MouseEvent)=>void,img=null,shown=_=>true,enabled=_=>true){ addsubmenu(text:string,onclick:(e:MouseEvent)=>void,img=null,shown=_=>true,enabled=_=>true){

View file

@ -108,7 +108,7 @@ class Group extends Channel{
this.messageids=new Map(); this.messageids=new Map();
this.permission_overwrites=new Map(); this.permission_overwrites=new Map();
this.lastmessageid=SnowFlake.getSnowFlakeFromID(json.last_message_id,Message); this.lastmessageid=SnowFlake.getSnowFlakeFromID(json.last_message_id,Message);
this.lastmessageid??=new SnowFlake("0",undefined); this.lastmessageid??=null;
this.mentions=0; this.mentions=0;
this.setUpInfiniteScroller(); this.setUpInfiniteScroller();
this.position=Math.max(this.lastmessageid.getUnixTime(),this.snowflake.getUnixTime()); this.position=Math.max(this.lastmessageid.getUnixTime(),this.snowflake.getUnixTime());

View file

@ -18,7 +18,7 @@ class Guild{
properties properties
roles:Role[]; roles:Role[];
roleids:Map<SnowFlake<Role>,Role>; roleids:Map<SnowFlake<Role>,Role>;
prevchannel:Channel; prevchannel:Channel|undefined;
message_notifications:number; message_notifications:number;
headchannels:Channel[]; headchannels:Channel[];
position:number; position:number;
@ -75,15 +75,15 @@ class Guild{
const settings=new Settings("Settings for "+this.properties.name); const settings=new Settings("Settings for "+this.properties.name);
const s1=settings.addButton("roles"); const s1=settings.addButton("roles");
const permlist=[]; const permlist:[SnowFlake<Role>,Permissions][]=[];
for(const thing of this.roles){ for(const thing of this.roles){
permlist.push([thing.snowflake,thing.permissions]); permlist.push([thing.snowflake,thing.permissions]);
} }
s1.options.push(new RoleList(permlist,this,this.updateRolePermissions.bind(this))); s1.options.push(new RoleList(permlist,this,this.updateRolePermissions.bind(this)));
settings.show(); settings.show();
} }
constructor(json:guildjson|-1,owner:Localuser,member:memberjson|User){ constructor(json:guildjson|-1,owner:Localuser,member:memberjson|User|null){
if(json===-1){ if(json===-1||member===null){
return; return;
} }
if(json.stickers.length){ if(json.stickers.length){
@ -118,7 +118,9 @@ class Guild{
} }
this.headchannels=[]; this.headchannels=[];
for(const thing of this.channels){ for(const thing of this.channels){
if(thing.resolveparent(this)){ const parent=thing.resolveparent(this);
console.log(parent,":3")
if(!parent){
this.headchannels.push(thing); this.headchannels.push(thing);
} }
} }
@ -333,7 +335,7 @@ class Guild{
headers:this.headers, headers:this.headers,
}) })
} }
unreads(html=undefined){ unreads(html:HTMLElement|undefined=undefined){
if(html){ if(html){
this.html=html; this.html=html;
}else{ }else{
@ -355,11 +357,14 @@ class Guild{
} }
} }
getHTML(){ getHTML(){
console.log("found :3",this.headchannels)
//this.printServers(); //this.printServers();
this.sortchannels(); this.sortchannels();
this.printServers(); this.printServers();
const build=document.createElement("div"); const build=document.createElement("div");
for(const thing of this.headchannels){ for(const thing of this.headchannels){
console.log("found :3")
build.appendChild(thing.createguildHTML(this.isAdmin())); build.appendChild(thing.createguildHTML(this.isAdmin()));
} }
return build; return build;

View file

@ -23,7 +23,6 @@ class Localuser{
initialized:boolean; initialized:boolean;
info:Specialuser["serverurls"]; info:Specialuser["serverurls"];
headers:{"Content-type":string,Authorization:string}; headers:{"Content-type":string,Authorization:string};
usersettings:Settings;
userConnections:Dialog; userConnections:Dialog;
devPortal:Dialog; devPortal:Dialog;
ready:readyjson; ready:readyjson;
@ -31,10 +30,10 @@ class Localuser{
guildids:Map<string,Guild>; guildids:Map<string,Guild>;
user:User; user:User;
status:string; status:string;
channelfocus:Channel; channelfocus:Channel|null;
lookingguild:Guild; lookingguild:Guild|null;
guildhtml:Map<string, HTMLDivElement>; guildhtml:Map<string, HTMLDivElement>;
ws:WebSocket; ws:WebSocket|undefined;
typing:Map<Member,number>=new Map(); typing:Map<Member,number>=new Map();
connectionSucceed=0; connectionSucceed=0;
errorBackoff=0; errorBackoff=0;
@ -51,14 +50,13 @@ class Localuser{
this.headers={"Content-type": "application/json; charset=UTF-8",Authorization:this.userinfo.token}; this.headers={"Content-type": "application/json; charset=UTF-8",Authorization:this.userinfo.token};
} }
gottenReady(ready:readyjson):void{ gottenReady(ready:readyjson):void{
this.usersettings=null;
this.initialized=true; this.initialized=true;
this.ready=ready; this.ready=ready;
this.guilds=[]; this.guilds=[];
this.guildids=new Map(); this.guildids=new Map();
this.user=new User(ready.d.user,this); this.user=new User(ready.d.user,this);
this.user.setstatus("online"); this.user.setstatus("online");
this.mfa_enabled=ready.d.user.mfa_enabled; this.mfa_enabled=ready.d.user.mfa_enabled as boolean;
this.userinfo.username=this.user.username; this.userinfo.username=this.user.username;
this.userinfo.pfpsrc=this.user.getpfpsrc(); this.userinfo.pfpsrc=this.user.getpfpsrc();
this.status=this.ready.d.user_settings.status; this.status=this.ready.d.user_settings.status;
@ -84,7 +82,7 @@ class Localuser{
for(const thing of ready.d.user_guild_settings.entries){ for(const thing of ready.d.user_guild_settings.entries){
this.guildids.get(thing.guild_id).notisetting(thing); (this.guildids.get(thing.guild_id) as Guild).notisetting(thing);
} }
for(const thing of ready.d.read_state.entries){ for(const thing of ready.d.read_state.entries){
@ -95,12 +93,14 @@ class Localuser{
continue continue
} }
const guildid=guild.snowflake; const guildid=guild.snowflake;
this.guildids.get(guildid.id).channelids[thing.channel_id].readStateInfo(thing); (this.guildids.get(guildid.id) as Guild).channelids[thing.channel_id].readStateInfo(thing);
} }
} }
outoffocus():void{ outoffocus():void{
document.getElementById("servers").innerHTML=""; const servers=document.getElementById("servers") as HTMLDivElement;
document.getElementById("channels").innerHTML=""; servers.innerHTML="";
const channels=document.getElementById("channels") as HTMLDivElement;
channels.innerHTML="";
if(this.channelfocus){ if(this.channelfocus){
this.channelfocus.infinite.delete(); this.channelfocus.infinite.delete();
} }
@ -120,33 +120,9 @@ class Localuser{
} }
swapped=false; swapped=false;
async initwebsocket():Promise<void>{ async initwebsocket():Promise<void>{
let returny=null let returny:()=>void;
const promise=new Promise((res)=>{returny=res}); const ws= new WebSocket(this.serverurls.gateway.toString()+"?encoding=json&v=9"+(DecompressionStream?"&compress=zlib-stream":""));;
this.ws = new WebSocket(this.serverurls.gateway.toString()+"?encoding=json&v=9"+(DecompressionStream?"&compress=zlib-stream":"")); this.ws=ws;
this.ws.addEventListener('open', (_event) => {
console.log('WebSocket connected');
this.ws.send(JSON.stringify({
"op": 2,
"d": {
"token":this.token,
"capabilities": 16381,
"properties": {
"browser": "Jank Client",
"client_build_number": 0,//might update this eventually lol
"release_channel": "Custom",
"browser_user_agent": navigator.userAgent
},
"compress": !!DecompressionStream,
"presence": {
"status": "online",
"since": null,//new Date().getTime()
"activities": [],
"afk": false
}
}
}))
});
let ds:DecompressionStream; let ds:DecompressionStream;
let w:WritableStreamDefaultWriter; let w:WritableStreamDefaultWriter;
let r:ReadableStreamDefaultReader; let r:ReadableStreamDefaultReader;
@ -157,71 +133,99 @@ class Localuser{
w= ds.writable.getWriter(); w= ds.writable.getWriter();
r=ds.readable.getReader(); r=ds.readable.getReader();
arr=new Uint8Array(); arr=new Uint8Array();
const textdecode=new TextDecoder();
(async ()=>{
while(true){
const read=await r.read();
const data=textdecode.decode(read.value);
build+=data;
try{
const temp=JSON.parse(build);
build="";
if(temp.op===0&&temp.t==="READY"){
returny();
}
await this.handleEvent(temp);
}catch{}
}
})();
} }
const promise=new Promise<void>((res)=>{
returny=res
let order=new Promise<void>((res)=>(res())); ws.addEventListener('open', (_event) => {
console.log('WebSocket connected');
this.ws.addEventListener('message', async (event) => { ws.send(JSON.stringify({
const temp2=order; "op": 2,
let res:Function; "d": {
order=new Promise<void>((r)=>(res=r)) "token":this.token,
await temp2; "capabilities": 16381,
let temp:{op:number,t:string}; "properties": {
try{ "browser": "Jank Client",
if(event.data instanceof Blob){ "client_build_number": 0,//might update this eventually lol
const buff=await event.data.arrayBuffer() "release_channel": "Custom",
const array=new Uint8Array(buff); "browser_user_agent": navigator.userAgent
},
const temparr=new Uint8Array(array.length+arr.length); "compress": !!DecompressionStream,
temparr.set(arr, 0); "presence": {
temparr.set(array, arr.length); "status": "online",
arr=temparr; "since": null,//new Date().getTime()
"activities": [],
const len=array.length; "afk": false
if(!(array[len-1]===255&&array[len-2]===255&&array[len-3]===0&&array[len-4]===0)){ }
return;
} }
w.write(arr.buffer); }))
arr=new Uint8Array(); });
return;//had to move the while loop due to me being dumb const textdecode=new TextDecoder();
}else{ if(DecompressionStream){
temp=JSON.parse(event.data); (async ()=>{
} while(true){
if(temp.op===0&&temp.t==="READY"){ const read=await r.read();
returny(); const data=textdecode.decode(read.value);
} build+=data;
await this.handleEvent(temp); try{
}catch(e){ const temp=JSON.parse(build);
console.error(e); build="";
}finally{ if(temp.op===0&&temp.t==="READY"){
res(); returny();
}
await this.handleEvent(temp);
}catch{}
}
})();
} }
}); });
this.ws.addEventListener("close",async event => { let order=new Promise<void>((res)=>(res()));
ws.addEventListener('message', async (event) => {
const temp2=order;
order=new Promise<void>(async (res)=>{
await temp2;
let temp:{op:number,t:string};
try{
if(event.data instanceof Blob){
const buff=await event.data.arrayBuffer()
const array=new Uint8Array(buff);
const temparr=new Uint8Array(array.length+arr.length);
temparr.set(arr, 0);
temparr.set(array, arr.length);
arr=temparr;
const len=array.length;
if(!(array[len-1]===255&&array[len-2]===255&&array[len-3]===0&&array[len-4]===0)){
return;
}
w.write(arr.buffer);
arr=new Uint8Array();
return;//had to move the while loop due to me being dumb
}else{
temp=JSON.parse(event.data);
}
if(temp.op===0&&temp.t==="READY"){
returny();
}
await this.handleEvent(temp);
}catch(e){
console.error(e);
}finally{
res();
}
})
});
ws.addEventListener("close",async event => {
this.ws=undefined; this.ws=undefined;
console.log("WebSocket closed with code " + event.code); console.log("WebSocket closed with code " + event.code);
this.unload(); this.unload();
document.getElementById("loading").classList.remove("doneloading"); (document.getElementById("loading") as HTMLElement).classList.remove("doneloading");
document.getElementById("loading").classList.add("loading"); (document.getElementById("loading") as HTMLElement).classList.add("loading");
this.fetchingmembers=new Map(); this.fetchingmembers=new Map();
this.noncemap=new Map(); this.noncemap=new Map();
this.noncebuild=new Map(); this.noncebuild=new Map();
@ -230,7 +234,7 @@ class Localuser{
else this.errorBackoff++; else this.errorBackoff++;
this.connectionSucceed=0; this.connectionSucceed=0;
document.getElementById("load-desc").innerHTML="Unable to connect to the Spacebar server, retrying in <b>" + Math.round(0.2 + (this.errorBackoff*2.8)) + "</b> seconds..."; (document.getElementById("load-desc") as HTMLElement).innerHTML="Unable to connect to the Spacebar server, retrying in <b>" + Math.round(0.2 + (this.errorBackoff*2.8)) + "</b> seconds...";
switch(this.errorBackoff){//try to recover from bad domain switch(this.errorBackoff){//try to recover from bad domain
case 3: case 3:
const newurls=await getapiurls(this.info.wellknown); const newurls=await getapiurls(this.info.wellknown);
@ -270,16 +274,17 @@ class Localuser{
} }
setTimeout(() => { setTimeout(() => {
if(this.swapped) return; if(this.swapped) return;
document.getElementById("load-desc").textContent="Retrying..."; (document.getElementById("load-desc") as HTMLElement).textContent="Retrying...";
this.initwebsocket().then(() => { this.initwebsocket().then(() => {
this.loaduser(); this.loaduser();
this.init(); this.init();
document.getElementById("loading").classList.add("doneloading"); const loading=document.getElementById("loading") as HTMLElement;
document.getElementById("loading").classList.remove("loading"); loading.classList.add("doneloading");
loading.classList.remove("loading");
console.log("done loading"); console.log("done loading");
}); });
}, 200 + (this.errorBackoff*2800)); }, 200 + (this.errorBackoff*2800));
} else document.getElementById("load-desc").textContent="Unable to connect to the Spacebar server. Please try logging out and back in."; } else (document.getElementById("load-desc") as HTMLElement).textContent="Unable to connect to the Spacebar server. Please try logging out and back in.";
}); });
await promise; await promise;
@ -338,9 +343,11 @@ class Localuser{
case "GUILD_DELETE": case "GUILD_DELETE":
{ {
const guildy=this.guildids.get(temp.d.id); const guildy=this.guildids.get(temp.d.id);
this.guildids.delete(temp.d.id); if(guildy){
this.guilds.splice(this.guilds.indexOf(guildy),1); this.guildids.delete(temp.d.id);
guildy.html.remove(); this.guilds.splice(this.guilds.indexOf(guildy),1);
guildy.html.remove();
}
break; break;
} }
case "GUILD_CREATE": case "GUILD_CREATE":
@ -348,7 +355,7 @@ class Localuser{
const guildy=new Guild(temp.d,this,this.user); const guildy=new Guild(temp.d,this,this.user);
this.guilds.push(guildy); this.guilds.push(guildy);
this.guildids.set(guildy.id,guildy); this.guildids.set(guildy.id,guildy);
document.getElementById("servers").insertBefore(guildy.generateGuildIcon(),document.getElementById("bottomseparator")); (document.getElementById("servers") as HTMLDivElement).insertBefore(guildy.generateGuildIcon(),document.getElementById("bottomseparator"));
break; break;
} }
case "MESSAGE_REACTION_ADD": case "MESSAGE_REACTION_ADD":
@ -379,6 +386,7 @@ class Localuser{
} }
}else if(temp.op===10){ }else if(temp.op===10){
if(!this.ws) return;
console.log("heartbeat down"); console.log("heartbeat down");
this.heartbeat_interval=temp.d.heartbeat_interval; this.heartbeat_interval=temp.d.heartbeat_interval;
this.ws.send(JSON.stringify({op:1,d:this.lastSequence})) this.ws.send(JSON.stringify({op:1,d:this.lastSequence}))
@ -391,7 +399,7 @@ class Localuser{
} }
} }
heartbeat_interval:number; heartbeat_interval:number;
resolveChannelFromID(ID:string):Channel{ resolveChannelFromID(ID:string):Channel|undefined{
let resolve=this.guilds.find(guild => guild.channelids[ID]); let resolve=this.guilds.find(guild => guild.channelids[ID]);
if(resolve){ if(resolve){
return resolve.channelids[ID]; return resolve.channelids[ID];
@ -400,22 +408,26 @@ class Localuser{
} }
updateChannel(json:channeljson):void{ updateChannel(json:channeljson):void{
SnowFlake.getSnowFlakeFromID(json.guild_id,Guild).getObject().updateChannel(json); SnowFlake.getSnowFlakeFromID(json.guild_id,Guild).getObject().updateChannel(json);
if(json.guild_id===this.lookingguild.id){ if(json.guild_id===this.lookingguild?.id){
this.loadGuild(json.guild_id); this.loadGuild(json.guild_id);
} }
} }
createChannel(json:channeljson):void{ createChannel(json:channeljson):void{
json.guild_id??="@me"; json.guild_id??="@me";
SnowFlake.getSnowFlakeFromID(json.guild_id,Guild).getObject().createChannelpac(json); SnowFlake.getSnowFlakeFromID(json.guild_id,Guild).getObject().createChannelpac(json);
if(json.guild_id===this.lookingguild.id){ if(json.guild_id===this.lookingguild?.id){
this.loadGuild(json.guild_id); this.loadGuild(json.guild_id);
} }
} }
delChannel(json:channeljson):void{ delChannel(json:channeljson):void{
json.guild_id??="@me"; let guild_id=json.guild_id;
this.guildids.get(json.guild_id).delChannel(json); guild_id??="@me";
const guild=this.guildids.get(guild_id);
if(guild){
guild.delChannel(json);
}
if(json.guild_id===this.lookingguild.id){ if(json.guild_id===this.lookingguild?.id){
this.loadGuild(json.guild_id); this.loadGuild(json.guild_id);
} }
} }
@ -424,20 +436,25 @@ class Localuser{
this.buildservers(); this.buildservers();
if(location[3]==="channels"){ if(location[3]==="channels"){
const guild=this.loadGuild(location[4]); const guild=this.loadGuild(location[4]);
if(!guild){return;}
guild.loadChannel(location[5]); guild.loadChannel(location[5]);
this.channelfocus=guild.channelids[location[5]]; this.channelfocus=guild.channelids[location[5]];
} }
} }
loaduser():void{ loaduser():void{
document.getElementById("username").textContent=this.user.username; (document.getElementById("username") as HTMLSpanElement).textContent=this.user.username;
(document.getElementById("userpfp") as HTMLImageElement).src=this.user.getpfpsrc(); (document.getElementById("userpfp") as HTMLImageElement).src=this.user.getpfpsrc();
document.getElementById("status").textContent=this.status; (document.getElementById("status") as HTMLSpanElement).textContent=this.status;
} }
isAdmin():boolean{ isAdmin():boolean{
return this.lookingguild.isAdmin(); if(this.lookingguild){
return this.lookingguild.isAdmin();
}else{
return false;
}
} }
loadGuild(id:string):Guild{ loadGuild(id:string):Guild|undefined{
let guild=this.guildids.get(id); let guild=this.guildids.get(id);
if(!guild){ if(!guild){
guild=this.guildids.get("@me"); guild=this.guildids.get("@me");
@ -445,18 +462,23 @@ class Localuser{
if(this.lookingguild){ if(this.lookingguild){
this.lookingguild.html.classList.remove("serveropen"); this.lookingguild.html.classList.remove("serveropen");
} }
if(!guild) return;
if(guild.html){ if(guild.html){
guild.html.classList.add("serveropen") guild.html.classList.add("serveropen")
} }
this.lookingguild=guild; this.lookingguild=guild;
document.getElementById("serverName").textContent=guild.properties.name; (document.getElementById("serverName") as HTMLElement).textContent=guild.properties.name;
//console.log(this.guildids,id) //console.log(this.guildids,id)
document.getElementById("channels").innerHTML=""; const channels=document.getElementById("channels") as HTMLDivElement;
document.getElementById("channels").appendChild(guild.getHTML()); channels.innerHTML="";
const html=guild.getHTML();
channels.appendChild(html);
console.log("found :3",html)
return guild; return guild;
} }
buildservers():void{ buildservers():void{
const serverlist=document.getElementById("servers");// const serverlist=document.getElementById("servers") as HTMLDivElement;//
const outdiv=document.createElement("div"); const outdiv=document.createElement("div");
const img=document.createElement("img"); const img=document.createElement("img");
const div=document.createElement("div"); const div=document.createElement("div");
@ -465,7 +487,7 @@ class Localuser{
img.src="/icons/home.svg"; img.src="/icons/home.svg";
img.classList.add("svgtheme","svgicon") img.classList.add("svgtheme","svgicon")
img["all"]=this.guildids.get("@me"); img["all"]=this.guildids.get("@me");
this.guildids.get("@me").html=outdiv; (this.guildids.get("@me") as Guild).html=outdiv;
const unread=document.createElement("div"); const unread=document.createElement("div");
unread.classList.add("unread"); unread.classList.add("unread");
outdiv.append(unread); outdiv.append(unread);
@ -524,7 +546,7 @@ class Localuser{
createGuild(){ createGuild(){
let inviteurl=""; let inviteurl="";
const error=document.createElement("span"); const error=document.createElement("span");
const fields:{name:string,icon:string}={ const fields:{name:string,icon:string|null}={
name:"", name:"",
icon:null, icon:null,
} }
@ -566,8 +588,9 @@ class Localuser{
["vdiv", ["vdiv",
["title","Create a guild"], ["title","Create a guild"],
["fileupload","Icon:",function(event:InputEvent){ ["fileupload","Icon:",function(event:InputEvent){
const reader=new FileReader();
const target=event.target as HTMLInputElement; const target=event.target as HTMLInputElement;
if(!target.files) return;
const reader=new FileReader();
reader.readAsDataURL(target.files[0]); reader.readAsDataURL(target.files[0]);
reader.onload=() => { reader.onload=() => {
fields.icon=reader.result as string; fields.icon=reader.result as string;
@ -590,7 +613,7 @@ class Localuser{
]]) ]])
full.show(); full.show();
} }
async makeGuild(fields:{name:string,icon:string}){ async makeGuild(fields:{name:string,icon:string|null}){
return await (await fetch(this.info.api+"/guilds",{ return await (await fetch(this.info.api+"/guilds",{
method:"POST", method:"POST",
headers:this.headers, headers:this.headers,
@ -660,7 +683,9 @@ class Localuser{
} }
messageCreate(messagep):void{ messageCreate(messagep):void{
messagep.d.guild_id??="@me"; messagep.d.guild_id??="@me";
this.guildids.get(messagep.d.guild_id).channelids[messagep.d.channel_id].messageCreate(messagep); const guild=this.guildids.get(messagep.d.guild_id);
if(!guild) return;
guild.channelids[messagep.d.channel_id].messageCreate(messagep);
this.unreads(); this.unreads();
} }
unreads():void{ unreads():void{
@ -671,9 +696,10 @@ class Localuser{
} }
} }
async typingStart(typing):Promise<void>{ async typingStart(typing):Promise<void>{
if(this.channelfocus.id===typing.d.channel_id){ if(this.channelfocus?.id===typing.d.channel_id){
const guild=this.guildids.get(typing.d.guild_id); const guild=this.guildids.get(typing.d.guild_id);
if(!guild) return;
const memb=await Member.new(typing.d.member,guild); const memb=await Member.new(typing.d.member,guild);
if(memb.id===this.user.id){ if(memb.id===this.user.id){
console.log("you is typing") console.log("you is typing")
@ -732,13 +758,13 @@ class Localuser{
}); });
} }
rendertyping():void{ rendertyping():void{
const typingtext=document.getElementById("typing") const typingtext=document.getElementById("typing") as HTMLDivElement;
let build=""; let build="";
let showing=false; let showing=false;
let i=0; let i=0;
const curtime=new Date().getTime()-5000; const curtime=new Date().getTime()-5000;
for(const thing of this.typing.keys()){ for(const thing of this.typing.keys()){
if(this.typing.get(thing)>curtime){ if(this.typing.get(thing) as number>curtime){
if(i!==0){ if(i!==0){
build+=", "; build+=", ";
} }
@ -760,20 +786,20 @@ class Localuser{
} }
if(showing){ if(showing){
typingtext.classList.remove("hidden"); typingtext.classList.remove("hidden");
document.getElementById("typingtext").textContent=build; const typingtext2=document.getElementById("typingtext") as HTMLDivElement;
typingtext2.textContent=build;
}else{ }else{
typingtext.classList.add("hidden"); typingtext.classList.add("hidden");
} }
} }
showusersettings(){ showusersettings(){
const settings=new Settings("Settings"); const settings=new Settings("Settings");
this.usersettings=settings;
{ {
const userOptions=settings.addButton("User Settings",{ltr:true}); const userOptions=settings.addButton("User Settings",{ltr:true});
const hypotheticalProfile=document.createElement("div"); const hypotheticalProfile=document.createElement("div");
let file=undefined; let file:undefined|File=undefined;
let newpronouns:string=undefined; let newpronouns:string|undefined=undefined;
let newbio:string=undefined; let newbio:string|undefined=undefined;
let hypouser=this.user.clone(); let hypouser=this.user.clone();
let color:string; let color:string;
async function regen(){ async function regen(){
@ -801,7 +827,7 @@ class Localuser{
regen(); regen();
} }
}); });
let bfile=undefined; let bfile:undefined|File|null=undefined;
const binput=settingsLeft.addFileInput("Upload banner:",_=>{ const binput=settingsLeft.addFileInput("Upload banner:",_=>{
if(bfile!==undefined){ if(bfile!==undefined){
this.updatebanner(bfile) this.updatebanner(bfile)
@ -863,7 +889,7 @@ class Localuser{
tas.addSelect("Theme:",_=>{ tas.addSelect("Theme:",_=>{
localStorage.setItem("theme",themes[_]); localStorage.setItem("theme",themes[_]);
setTheme(); setTheme();
},themes,{defaultIndex:themes.indexOf(localStorage.getItem("theme"))}); },themes,{defaultIndex:themes.indexOf(localStorage.getItem("theme") as string)});
} }
{ {
const sounds=Voice.sounds; const sounds=Voice.sounds;
@ -1217,15 +1243,16 @@ class Localuser{
readonly presences:Map<string,presencejson>=new Map(); readonly presences:Map<string,presencejson>=new Map();
async resolvemember(id:string,guildid:string):Promise<memberjson|undefined>{ async resolvemember(id:string,guildid:string):Promise<memberjson|undefined>{
if(guildid==="@me"){return undefined} if(guildid==="@me"){return undefined}
if(!this.waitingmembers.has(guildid)){ let guildmap=this.waitingmembers.get(guildid);
this.waitingmembers.set(guildid,new Map()); if(!guildmap){
guildmap=new Map();
this.waitingmembers.set(guildid,guildmap);
} }
let res:(returns:memberjson|undefined)=>void; const promise:Promise<memberjson|undefined>=new Promise((res)=>{
const promise:Promise<memberjson|undefined>=new Promise((r)=>{ guildmap.set(id,res);
res=r; this.getmembers();
}) })
this.waitingmembers.get(guildid).set(id,res);
this.getmembers();
return await promise; return await promise;
} }
fetchingmembers:Map<string,boolean>=new Map(); fetchingmembers:Map<string,boolean>=new Map();
@ -1233,11 +1260,14 @@ class Localuser{
noncebuild:Map<string,[memberjson[],string[],number[]]>=new Map(); noncebuild:Map<string,[memberjson[],string[],number[]]>=new Map();
async gotChunk(chunk:{chunk_index:number,chunk_count:number,nonce:string,not_found?:string[],members?:memberjson[],presences:presencejson[]}){ async gotChunk(chunk:{chunk_index:number,chunk_count:number,nonce:string,not_found?:string[],members?:memberjson[],presences:presencejson[]}){
for(const thing of chunk.presences){ for(const thing of chunk.presences){
this.presences.set(thing.user.id,thing); if(thing.user){
this.presences.set(thing.user.id,thing);
}
} }
console.log(chunk); console.log(chunk);
chunk.members??=[]; chunk.members??=[];
const arr=this.noncebuild.get(chunk.nonce); const arr=this.noncebuild.get(chunk.nonce);
if(!arr) return;
arr[0]=arr[0].concat(chunk.members); arr[0]=arr[0].concat(chunk.members);
if(chunk.not_found){ if(chunk.not_found){
arr[1]=chunk.not_found; arr[1]=chunk.not_found;
@ -1247,15 +1277,14 @@ class Localuser{
console.log("got through"); console.log("got through");
this.noncebuild.delete(chunk.nonce); this.noncebuild.delete(chunk.nonce);
const func=this.noncemap.get(chunk.nonce) const func=this.noncemap.get(chunk.nonce)
if(!func) return;
func([arr[0],arr[1]]); func([arr[0],arr[1]]);
this.noncemap.delete(chunk.nonce); this.noncemap.delete(chunk.nonce);
} }
} }
async getmembers(){ async getmembers(){
let res:Function const promise=new Promise(res=>{setTimeout(res,10)});
const promise=new Promise(r=>res=r);
setTimeout(res,10);
await promise;//allow for more to be sent at once :P await promise;//allow for more to be sent at once :P
if(this.ws){ if(this.ws){
this.waitingmembers.forEach(async (value,guildid)=>{ this.waitingmembers.forEach(async (value,guildid)=>{
@ -1269,35 +1298,39 @@ class Localuser{
this.waitingmembers.delete(guildid); this.waitingmembers.delete(guildid);
return return
}; };
let res:(r:[memberjson[],string[]])=>void; const promise:Promise<[memberjson[],string[]]>=new Promise((res)=>{
const promise:Promise<[memberjson[],string[]]>=new Promise((r)=>{ const nonce=""+Math.floor(Math.random()*100000000000);
res=r; this.noncemap.set(nonce,res);
this.noncebuild.set(nonce,[[],[],[]]);
if(!this.ws) return;
this.ws.send(JSON.stringify({
op:8,
d:{
user_ids:build,
guild_id:guildid,
limit:100,
nonce,
presences:true
}
}));
this.fetchingmembers.set(guildid,true);
}) })
const nonce=""+Math.floor(Math.random()*100000000000);
this.noncemap.set(nonce,res);
this.noncebuild.set(nonce,[[],[],[]]);
this.ws.send(JSON.stringify({
op:8,
d:{
user_ids:build,
guild_id:guildid,
limit:100,
nonce,
presences:true
}
}));
this.fetchingmembers.set(guildid,true);
const prom=await promise;; const prom=await promise;;
const data=prom[0]; const data=prom[0];
for(const thing of data){ for(const thing of data){
if(value.has(thing.id)){ if(value.has(thing.id)){
value.get(thing.id)(thing); const func=value.get(thing.id);
if(!func) continue;
func(thing);
value.delete(thing.id); value.delete(thing.id);
} }
} }
for(const thing of prom[1]){ for(const thing of prom[1]){
if(value.has(thing)){ if(value.has(thing)){
value.get(thing)(undefined); const func=value.get(thing)
if(!func) continue;
func(undefined);
value.delete(thing); value.delete(thing);
} }
} }
@ -1341,7 +1374,7 @@ let fixsvgtheme:Function;
h=(g-b)/(max-min); h=(g-b)/(max-min);
}else if(g===max){ }else if(g===max){
h=2+(b-r)/(max-min); h=2+(b-r)/(max-min);
}else if(b===max){ }else{
h=4+(r-g)/(max-min); h=4+(r-g)/(max-min);
} }
}else{ }else{

View file

@ -198,7 +198,7 @@ class Message{
} }
} }
getimages(){ getimages(){
const build=[]; const build:File[]=[];
for(const thing of this.attachments){ for(const thing of this.attachments){
if(thing.content_type.startsWith('image/')){ if(thing.content_type.startsWith('image/')){
build.push(thing); build.push(thing);

View file

@ -20,7 +20,7 @@ class User{
bot:boolean; bot:boolean;
public_flags: number; public_flags: number;
accent_color: number; accent_color: number;
banner: string; banner: string|null|undefined;
hypotheticalbanner:boolean; hypotheticalbanner:boolean;
premium_since: string; premium_since: string;
premium_type: number; premium_type: number;