TS conversion

This commit is contained in:
MathMan05 2024-06-27 11:27:38 -05:00
parent 75fa9d0844
commit 845c7f6612
44 changed files with 6225 additions and 611 deletions

138
.dist/audio.js Normal file
View file

@ -0,0 +1,138 @@
import { getBulkInfo } from "./login.js";
class Voice {
audioCtx;
info;
playing;
myArrayBuffer;
gainNode;
buffer;
source;
constructor(wave, freq, volume = 1) {
this.audioCtx = new (window.AudioContext)();
this.info = { wave: wave, freq: freq };
this.playing = false;
this.myArrayBuffer = this.audioCtx.createBuffer(1, this.audioCtx.sampleRate, this.audioCtx.sampleRate);
this.gainNode = this.audioCtx.createGain();
this.gainNode.gain.value = volume;
this.gainNode.connect(this.audioCtx.destination);
this.buffer = this.myArrayBuffer.getChannelData(0);
this.source = this.audioCtx.createBufferSource();
this.source.buffer = this.myArrayBuffer;
this.source.loop = true;
this.source.start();
this.updateWave();
}
get wave() {
return this.info.wave;
}
get freq() {
return this.info.freq;
}
set wave(wave) {
this.info.wave = wave;
this.updateWave();
}
set freq(freq) {
this.info.freq = freq;
this.updateWave();
}
updateWave() {
const func = this.waveFucnion();
for (let i = 0; i < this.buffer.length; i++) {
this.buffer[i] = func(i / this.audioCtx.sampleRate, this.freq);
}
}
waveFucnion() {
if (typeof this.wave === 'function') {
return this.wave;
}
switch (this.wave) {
case "sin":
return (t, freq) => {
return Math.sin(t * Math.PI * 2 * freq);
};
case "triangle":
return (t, freq) => {
return Math.abs((4 * t * freq) % 4 - 2) - 1;
};
case "sawtooth":
return (t, freq) => {
return ((t * freq) % 1) * 2 - 1;
};
case "square":
return (t, freq) => {
return (t * freq) % 2 < 1 ? 1 : -1;
};
case "white":
return (_t, _freq) => {
return Math.random() * 2 - 1;
};
case "noise":
return (_t, _freq) => {
return 0;
};
}
}
play() {
if (this.playing) {
return;
}
this.source.connect(this.gainNode);
this.playing = true;
}
stop() {
if (this.playing) {
this.source.disconnect();
this.playing = false;
}
}
static noises(noise) {
switch (noise) {
case "three": {
const voicy = new Voice("sin", 800);
voicy.play();
setTimeout(_ => { voicy.freq = 1000; }, 50);
setTimeout(_ => { voicy.freq = 1300; }, 100);
setTimeout(_ => { voicy.stop(); }, 150);
break;
}
case "zip": {
const voicy = new Voice((t, freq) => {
return Math.sin(((t + 2) ** (Math.cos(t * 4))) * Math.PI * 2 * freq);
}, 700);
voicy.play();
setTimeout(_ => { voicy.stop(); }, 150);
break;
}
case "square": {
const voicy = new Voice("square", 600, .4);
voicy.play();
setTimeout(_ => { voicy.freq = 800; }, 50);
setTimeout(_ => { voicy.freq = 1000; }, 100);
setTimeout(_ => { voicy.stop(); }, 150);
break;
}
case "beep": {
const voicy = new Voice("sin", 800);
voicy.play();
setTimeout(_ => { voicy.stop(); }, 50);
setTimeout(_ => { voicy.play(); }, 100);
setTimeout(_ => { voicy.stop(); }, 150);
break;
}
}
}
static get sounds() {
return ["three", "zip", "square", "beep"];
}
static setNotificationSound(sound) {
let userinfos = getBulkInfo();
userinfos.preferances.notisound = sound;
localStorage.setItem("userinfos", JSON.stringify(userinfos));
}
static getNotificationSound() {
let userinfos = getBulkInfo();
return userinfos.preferances.notisound;
}
}
export { Voice as Voice };

648
.dist/channel.js Normal file
View file

@ -0,0 +1,648 @@
"use strict";
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";
class Channel {
editing;
type;
owner;
headers;
messages;
name;
id;
parent_id;
parrent;
children;
guild_id;
messageids;
permission_overwrites;
topic;
nsfw;
position;
lastreadmessageid;
lastmessageid;
mentions;
lastpin;
move_id;
typing;
message_notifications;
allthewayup;
static contextmenu = new Contextmenu("channel menu");
static setupcontextmenu() {
Channel.contextmenu.addbutton("Copy channel id", function () {
console.log(this);
navigator.clipboard.writeText(this.id);
});
Channel.contextmenu.addbutton("Mark as read", function () {
console.log(this);
this.readbottom();
});
Channel.contextmenu.addbutton("Delete channel", function () {
console.log(this);
this.deleteChannel();
}, null, _ => { console.log(_); return _.isAdmin(); });
Channel.contextmenu.addbutton("Edit channel", function () {
this.editChannel(this);
}, null, _ => { return _.isAdmin(); });
}
constructor(JSON, owner) {
if (JSON === -1) {
return;
}
this.editing;
this.type = JSON.type;
this.owner = owner;
this.headers = this.owner.headers;
this.messages = [];
this.name = JSON.name;
this.id = JSON.id;
this.parent_id = JSON.parent_id;
this.parrent = null;
this.children = [];
this.guild_id = JSON.guild_id;
this.messageids = {};
this.permission_overwrites = {};
for (const thing of JSON.permission_overwrites) {
this.permission_overwrites[thing.id] = new Permissions(thing.allow, thing.deny);
}
console.log(this.permission_overwrites);
this.topic = JSON.topic;
this.nsfw = JSON.nsfw;
this.position = JSON.position;
this.lastreadmessageid = null;
this.lastmessageid = JSON.last_message_id;
}
isAdmin() {
return this.guild.isAdmin();
}
get guild() {
return this.owner;
}
get localuser() {
return this.guild.localuser;
}
get info() {
return this.owner.info;
}
readStateInfo(json) {
this.lastreadmessageid = json.last_message_id;
this.mentions = json.mention_count;
this.mentions ??= 0;
this.lastpin = json.last_pin_timestamp;
}
get hasunreads() {
return this.lastmessageid !== this.lastreadmessageid && this.type !== 4;
}
get canMessage() {
console.log("this should run");
for (const thing of Object.entries(this.permission_overwrites)) {
const perm = thing[1].getPermision("SEND_MESSAGES");
if (perm === 1) {
return true;
}
if (perm === -1) {
return false;
}
}
return true;
}
sortchildren() {
this.children.sort((a, b) => { return a.position - b.position; });
}
resolveparent(guild) {
this.parrent = guild.channelids[this.parent_id];
this.parrent ??= null;
if (this.parrent !== null) {
this.parrent.children.push(this);
}
return this.parrent === null;
}
calculateReorder() {
let position = -1;
let build = [];
for (const thing of this.children) {
const thisthing = { id: thing.id, position: undefined, parent_id: undefined };
if (thing.position < position) {
thing.position = thisthing.position = position + 1;
}
position = thing.position;
if (thing.move_id && thing.move_id !== thing.parent_id) {
thing.parent_id = thing.move_id;
thisthing.parent_id = thing.parent_id;
thing.move_id = undefined;
console.log(this.guild.channelids[thisthing.parent_id]);
}
if (thisthing.position || thisthing.parent_id) {
build.push(thisthing);
}
}
return build;
}
static dragged = [];
createguildHTML(admin = false) {
const div = document.createElement("div");
div["all"] = this;
div.draggable = admin;
div.addEventListener("dragstart", (e) => { Channel.dragged = [this, div]; e.stopImmediatePropagation(); });
div.addEventListener("dragend", () => { Channel.dragged = []; });
if (this.type === 4) {
this.sortchildren();
const caps = document.createElement("div");
const decdiv = document.createElement("div");
const decoration = document.createElement("b");
decoration.textContent = "▼";
decdiv.appendChild(decoration);
const myhtml = document.createElement("p2");
myhtml.textContent = this.name;
decdiv.appendChild(myhtml);
caps.appendChild(decdiv);
const childrendiv = document.createElement("div");
if (admin) {
const addchannel = document.createElement("span");
addchannel.textContent = "+";
addchannel.classList.add("addchannel");
caps.appendChild(addchannel);
addchannel.onclick = function () {
this.guild.createchannels(this.createChannel.bind(this));
}.bind(this);
this.coatDropDiv(decdiv, childrendiv);
}
div.appendChild(caps);
caps.classList.add("capsflex");
decdiv.classList.add("channeleffects");
decdiv.classList.add("channel");
Channel.contextmenu.bind(decdiv, this);
decdiv["all"] = this;
for (const channel of this.children) {
childrendiv.appendChild(channel.createguildHTML(admin));
}
childrendiv.classList.add("channels");
setTimeout(_ => { childrendiv.style.height = childrendiv.scrollHeight + 'px'; }, 100);
decdiv.onclick = function () {
if (decoration.textContent === "▼") { //
decoration.textContent = "▲";
//childrendiv.classList.add("colapsediv");
childrendiv.style.height = '0px';
}
else {
decoration.textContent = "▼";
//childrendiv.classList.remove("colapsediv")
childrendiv.style.height = childrendiv.scrollHeight + 'px';
}
};
div.appendChild(childrendiv);
}
else {
div.classList.add("channel");
if (this.hasunreads) {
div.classList.add("cunread");
}
Channel.contextmenu.bind(div, this);
if (admin) {
this.coatDropDiv(div);
}
div["all"] = this;
const myhtml = document.createElement("span");
myhtml.textContent = this.name;
if (this.type === 0) {
const decoration = document.createElement("b");
decoration.textContent = "#";
div.appendChild(decoration);
decoration.classList.add("space");
}
else if (this.type === 2) { //
const decoration = document.createElement("b");
decoration.textContent = "🕪";
div.appendChild(decoration);
decoration.classList.add("spacee");
}
else if (this.type === 5) { //
const decoration = document.createElement("b");
decoration.textContent = "📣";
div.appendChild(decoration);
decoration.classList.add("spacee");
}
else {
console.log(this.type);
}
div.appendChild(myhtml);
div.onclick = _ => {
this.getHTML();
};
}
return div;
}
get myhtml() {
const search = document.getElementById("channels").children[0].children;
if (this.guild !== this.localuser.lookingguild) {
return null;
}
else if (this.parrent) {
for (const thing of search) {
if (thing["all"] === this.parrent) {
for (const thing2 of thing.children[1].children) {
if (thing2["all"] === this) {
return thing2;
}
}
}
}
}
else {
for (const thing of search) {
if (thing["all"] === this) {
return thing;
}
}
}
return null;
}
readbottom() {
if (!this.hasunreads) {
return;
}
fetch(this.info.api.toString() + "/v9/channels/" + this.id + "/messages/" + this.lastmessageid + "/ack", {
method: "POST",
headers: this.headers,
body: JSON.stringify({})
});
this.lastreadmessageid = this.lastmessageid;
this.guild.unreads();
if (this.myhtml !== null) {
this.myhtml.classList.remove("cunread");
}
}
coatDropDiv(div, container = false) {
div.addEventListener("dragenter", (event) => {
console.log("enter");
event.preventDefault();
});
div.addEventListener("dragover", (event) => {
event.preventDefault();
});
div.addEventListener("drop", (event) => {
const that = Channel.dragged[0];
event.preventDefault();
if (container) {
that.move_id = this.id;
if (that.parrent) {
that.parrent.children.splice(that.parrent.children.indexOf(that), 1);
}
that.parrent = this;
container.prepend(Channel.dragged[1]);
this.children.unshift(that);
}
else {
console.log(this, Channel.dragged);
that.move_id = this.parent_id;
if (that.parrent) {
that.parrent.children.splice(that.parrent.children.indexOf(that), 1);
}
else {
this.guild.headchannels.splice(this.guild.headchannels.indexOf(that), 1);
}
that.parrent = this.parrent;
if (that.parrent) {
const build = [];
for (let i = 0; i < that.parrent.children.length; i++) {
build.push(that.parrent.children[i]);
if (that.parrent.children[i] === this) {
build.push(that);
}
}
that.parrent.children = build;
}
else {
const build = [];
for (let i = 0; i < this.guild.headchannels.length; i++) {
build.push(this.guild.headchannels[i]);
if (this.guild.headchannels[i] === this) {
build.push(that);
}
}
this.guild.headchannels = build;
}
div.after(Channel.dragged[1]);
}
this.guild.calculateReorder();
});
return div;
}
createChannel(name, type) {
fetch(this.info.api.toString() + "/guilds/" + this.guild.id + "/channels", {
method: "Post",
headers: this.headers,
body: JSON.stringify({
name: name,
type: type,
parent_id: this.id,
permission_overwrites: [],
})
});
}
editChannel() {
let name = this.name;
let topic = this.topic;
let nsfw = this.nsfw;
const thisid = this.id;
const thistype = this.type;
const full = new Fullscreen(["hdiv",
["vdiv",
["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, {
method: "PATCH",
headers: this.headers,
body: JSON.stringify({
"name": name,
"type": thistype,
"topic": topic,
"bitrate": 64000,
"user_limit": 0,
"nsfw": nsfw,
"flags": 0,
"rate_limit_per_user": 0
})
});
console.log(full);
full.hide();
}]
]
]);
full.show();
console.log(full);
}
deleteChannel() {
fetch(this.info.api.toString() + "/v9/channels/" + this.id, {
method: "DELETE",
headers: this.headers
});
}
getHTML() {
if (this.guild !== this.localuser.lookingguild) {
this.guild.loadGuild();
}
this.guild.prevchannel = this;
this.localuser.channelfocus = this;
this.putmessages();
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;
}
putmessages() {
const out = this;
fetch(this.info.api.toString() + "/channels/" + this.id + "/messages?limit=100", {
method: 'GET',
headers: this.headers,
}).then((j) => { return j.json(); }).then(responce => {
document.getElementById("messages").innerHTML = '';
for (const thing of responce) {
const messager = new Message(thing, this);
if (out.messageids[messager.id] == undefined) {
out.messageids[messager.id] = messager;
out.messages.push(messager);
}
}
out.buildmessages();
});
}
delChannel(JSON) {
const build = [];
for (const thing of this.children) {
if (thing.id !== JSON.id) {
build.push(thing);
}
}
this.children = build;
}
async grabmoremessages() {
if (this.messages.length === 0 || this.allthewayup) {
return;
}
const out = this;
await fetch(this.info.api.toString() + "/channels/" + this.id + "/messages?before=" + this.messages[this.messages.length - 1].id + "&limit=100", {
method: "GET",
headers: this.headers
}).then((j) => { return j.json(); }).then(responce => {
//messages.innerHTML = '';
//responce.reverse()
let next;
if (responce.length === 0) {
out.allthewayup = true;
}
for (const i in responce) {
let messager;
if (!next) {
messager = new Message(responce[i], this);
}
else {
messager = next;
}
if (responce[+i + 1] !== undefined) {
next = new Message(responce[+i + 1], this);
}
else {
next = undefined;
console.log("ohno", +i + 1);
}
if (out.messageids[messager.id] == undefined) {
out.messageids[messager.id] = messager;
out.buildmessage(messager, next);
out.messages.push(messager);
}
else {
console.log("How???");
}
}
//out.buildmessages();
});
return;
}
buildmessage(message, next) {
const built = message.buildhtml(next);
document.getElementById("messages").prepend(built);
}
buildmessages() {
for (const i in this.messages) {
const prev = this.messages[(+i) + 1];
const built = this.messages[i].buildhtml(prev);
document.getElementById("messages").prepend(built);
}
document.getElementById("messagecontainer").scrollTop = document.getElementById("messagecontainer").scrollHeight;
}
updateChannel(JSON) {
this.type = JSON.type;
this.name = JSON.name;
this.parent_id = JSON.parent_id;
this.parrent = null;
this.children = [];
this.guild_id = JSON.guild_id;
this.messageids = {};
this.permission_overwrites = JSON.permission_overwrites;
this.topic = JSON.topic;
this.nsfw = JSON.nsfw;
}
typingstart() {
if (this.typing > new Date().getTime()) {
return;
}
this.typing = new Date().getTime() + 6000;
fetch(this.info.api.toString() + "/channels/" + this.id + "/typing", {
method: "POST",
headers: this.headers
});
}
get notification() {
let notinumber = this.message_notifications;
if (+notinumber === 3) {
notinumber = null;
}
notinumber ??= this.guild.message_notifications;
switch (+notinumber) {
case 0:
return "all";
case 1:
return "mentions";
case 2:
return "none";
case 3:
return "default";
}
}
async sendMessage(content, { attachments = [], embeds = [], replyingto = null }) {
let replyjson;
if (replyingto) {
replyjson =
{
"guild_id": replyingto.guild.id,
"channel_id": replyingto.channel.id,
"message_id": replyingto.id,
};
}
;
if (attachments.length === 0) {
const body = {
content: content,
nonce: Math.floor(Math.random() * 1000000000),
message_reference: undefined
};
if (replyjson) {
body.message_reference = replyjson;
}
console.log(body);
return await fetch(this.info.api.toString() + "/channels/" + this.id + "/messages", {
method: "POST",
headers: this.headers,
body: JSON.stringify(body)
});
}
else {
const formData = new FormData();
const body = {
content: content,
nonce: Math.floor(Math.random() * 1000000000),
message_reference: undefined
};
if (replyjson) {
body.message_reference = replyjson;
}
formData.append('payload_json', JSON.stringify(body));
for (const i in attachments) {
console.log(attachments[i]);
formData.append("files[" + i + "]", attachments[i]);
}
return await fetch(this.info.api.toString() + "/channels/" + this.id + "/messages", {
method: 'POST',
body: formData,
headers: { "Authorization": this.headers.Authorization }
});
}
}
messageCreate(messagep) {
const messagez = new Message(messagep.d, this);
this.lastmessageid = messagez.id;
if (messagez.author === this.localuser.user) {
this.lastreadmessageid = messagez.id;
if (this.myhtml) {
this.myhtml.classList.remove("cunread");
}
}
else {
if (this.myhtml) {
this.myhtml.classList.add("cunread");
}
}
this.guild.unreads();
this.messages.unshift(messagez);
const scrolly = document.getElementById("messagecontainer");
this.messageids[messagez.id] = messagez;
if (this.localuser.lookingguild.prevchannel === this) {
var shouldScroll = scrolly.scrollTop + scrolly.clientHeight > scrolly.scrollHeight - 20;
document.getElementById("messages").appendChild(messagez.buildhtml(this.messages[1]));
}
if (shouldScroll) {
scrolly.scrollTop = scrolly.scrollHeight;
}
if (messagez.author === this.localuser.user) {
return;
}
if (this.localuser.lookingguild.prevchannel === this && document.hasFocus()) {
return;
}
if (this.notification === "all") {
this.notify(messagez);
}
else if (this.notification === "mentions" && messagez.mentionsuser(this.localuser.user)) {
this.notify(messagez);
}
}
notititle(message) {
return message.author.username + " > " + this.guild.properties.name + " > " + this.name;
}
notify(message, deep = 0) {
Voice.noises(Voice.getNotificationSound());
if (!("Notification" in window)) {
}
else if (Notification.permission === "granted") {
let noticontent = markdown(message.content).textContent;
if (message.embeds[0]) {
noticontent ||= message.embeds[0].json.title;
noticontent ||= markdown(message.embeds[0].json.description).textContent;
}
noticontent ||= "Blank Message";
let imgurl = null;
const images = message.getimages();
if (images.length) {
const image = images[0];
imgurl ||= image.proxy_url;
imgurl ||= image.url;
}
const notification = new Notification(this.notititle(message), {
body: noticontent,
icon: message.author.getpfpsrc(),
image: imgurl,
});
notification.addEventListener("click", _ => {
window.focus();
this.getHTML();
});
}
else if (Notification.permission !== "denied") {
Notification.requestPermission().then(() => {
if (deep === 3) {
return;
}
;
this.notify(message, deep + 1);
});
}
}
}
Channel.setupcontextmenu();
export { Channel };

63
.dist/contextmenu.js Normal file
View file

@ -0,0 +1,63 @@
class Contextmenu {
static currentmenu;
name;
buttons;
div;
static setup() {
Contextmenu.currentmenu = "";
document.addEventListener('click', function (event) {
if (Contextmenu.currentmenu == "") {
return;
}
if (!Contextmenu.currentmenu.contains(event.target)) {
Contextmenu.currentmenu.remove();
Contextmenu.currentmenu = "";
}
});
}
constructor(name) {
this.name = name;
this.buttons = [];
}
addbutton(text, onclick, img = null, shown = _ => true, enabled = _ => true) {
this.buttons.push([text, onclick, img, shown, enabled]);
return {};
}
makemenu(x, y, addinfo, obj) {
const div = document.createElement("table");
div.classList.add("contextmenu");
for (const thing of this.buttons) {
if (!thing[3](addinfo)) {
continue;
}
const textb = document.createElement("tr");
const intext = document.createElement("button");
intext.disabled = !thing[4]();
textb["button"] = intext;
intext.classList.add("contextbutton");
intext.textContent = thing[0];
textb.appendChild(intext);
console.log(thing);
intext.onclick = thing[1].bind(addinfo, obj);
div.appendChild(textb);
}
if (Contextmenu.currentmenu != "") {
Contextmenu.currentmenu.remove();
}
div.style.top = y + 'px';
div.style.left = x + 'px';
document.body.appendChild(div);
console.log(div);
Contextmenu.currentmenu = div;
return this.div;
}
bind(obj, addinfo = undefined) {
obj.addEventListener("contextmenu", (event) => {
event.preventDefault();
event.stopImmediatePropagation();
this.makemenu(event.clientX, event.clientY, addinfo, obj);
});
}
}
Contextmenu.setup();
export { Contextmenu as Contextmenu };

190
.dist/direct.js Normal file
View file

@ -0,0 +1,190 @@
import { Guild } from "./guild.js";
import { Channel } from "./channel.js";
import { Message } from "./message.js";
import { User } from "./user.js";
class Direct extends Guild {
constructor(JSON, owner) {
super(-1, owner);
this.message_notifications = 0;
console.log(JSON);
this.owner = owner;
if (!this.localuser) {
console.error("Owner was not included, please fix");
}
this.headers = this.localuser.headers;
this.channels = [];
this.channelids = {};
this.id = "@me";
this.properties = {};
this.roles = [];
this.roleids = {};
this.prevchannel = undefined;
this.properties.name = "Dirrect Messages";
for (const thing of JSON) {
const temp = new Group(thing, this);
this.channels.push(temp);
this.channelids[temp.id] = temp;
}
this.headchannels = this.channels;
}
createChannelpac(JSON) {
const thischannel = new Group(JSON, this);
this.channelids[JSON.id] = thischannel;
this.channels.push(thischannel);
this.calculateReorder();
this.printServers();
}
sortchannels() {
this.headchannels.sort((a, b) => {
const result = (BigInt(a.lastmessageid) - BigInt(b.lastmessageid));
return Number(-result);
});
}
giveMember(member) {
console.error("not a real guild, can't give member object");
}
getRole(ID) {
return null;
}
hasRole(r) {
return false;
}
isAdmin() {
return false;
}
unreaddms() {
for (const thing of this.channels) {
thing.unreads();
}
}
}
class Group extends Channel {
user;
constructor(JSON, owner) {
super(-1, owner);
this.owner = owner;
this.headers = this.guild.headers;
this.messages = [];
this.name = JSON.recipients[0]?.username;
if (JSON.recipients[0]) {
this.user = new User(JSON.recipients[0], this.localuser);
}
else {
this.user = this.localuser.user;
}
this.name ??= this.localuser.user.username;
this.id = JSON.id;
this.parent_id = null;
this.parrent = null;
this.children = [];
this.guild_id = "@me";
this.messageids = {};
this.permission_overwrites = {};
this.lastmessageid = JSON.last_message_id;
this.lastmessageid ??= "0";
this.mentions = 0;
}
createguildHTML() {
const div = document.createElement("div");
div.classList.add("channeleffects");
const myhtml = document.createElement("span");
myhtml.textContent = this.name;
div.appendChild(this.user.buildpfp());
div.appendChild(myhtml);
div["myinfo"] = this;
div.onclick = _ => {
this.getHTML();
};
return div;
}
getHTML() {
this.guild.prevchannel = this;
this.localuser.channelfocus = this;
this.putmessages();
history.pushState(null, null, "/channels/" + this.guild_id + "/" + this.id);
document.getElementById("channelname").textContent = "@" + this.name;
}
messageCreate(messagep) {
const messagez = new Message(messagep.d, this);
this.lastmessageid = messagez.id;
if (messagez.author === this.localuser.user) {
this.lastreadmessageid = messagez.id;
}
this.messages.unshift(messagez);
const scrolly = document.getElementById("messagecontainer");
this.messageids[messagez.id] = messagez;
if (this.localuser.lookingguild.prevchannel === this) {
var shouldScroll = scrolly.scrollTop + scrolly.clientHeight > scrolly.scrollHeight - 20;
document.getElementById("messages").appendChild(messagez.buildhtml(this.messages[1]));
}
if (shouldScroll) {
scrolly.scrollTop = scrolly.scrollHeight;
}
console.log(document.getElementById("channels").children);
if (this.localuser.lookingguild === this.guild) {
const channellist = document.getElementById("channels").children[0];
for (const thing of channellist.children) {
if (thing["myinfo"] === this) {
channellist.prepend(thing);
break;
}
}
}
this.unreads();
if (messagez.author === this.localuser.user) {
return;
}
if (this.localuser.lookingguild.prevchannel === this && document.hasFocus()) {
return;
}
console.log(this.notification);
if (this.notification === "all") {
this.notify(messagez);
}
else if (this.notification === "mentions" && messagez.mentionsuser(this.localuser.user)) {
this.notify(messagez);
}
}
notititle(message) {
return message.author.username;
}
unreads() {
const sentdms = document.getElementById("sentdms");
let current = null;
for (const thing of sentdms.children) {
if (thing["all"] === this) {
current = thing;
}
}
if (this.hasunreads) {
if (current) {
current.noti.textContent = this.mentions;
return;
}
const div = document.createElement("div");
div.classList.add("servernoti");
const noti = document.createElement("div");
noti.classList.add("unread", "notiunread", "pinged");
noti.textContent = "" + this.mentions;
console.log(this.mentions);
div["noti"] = noti;
div.append(noti);
const buildpfp = this.user.buildpfp();
div["all"] = this;
buildpfp.classList.add("mentioned");
console.log(this);
div.append(buildpfp);
sentdms.append(div);
div.onclick = function () {
this["noti"].guild.loadGuild();
this["noti"].getHTML();
};
}
else if (current) {
current.remove();
}
else {
}
}
}
export { Direct, Group };

195
.dist/embed.js Normal file
View file

@ -0,0 +1,195 @@
import { Fullscreen } from "./fullscreen.js";
class Embed {
type;
owner;
json;
constructor(json, owner) {
this.type = this.getType(json);
this.owner = owner;
this.json = json;
}
getType(json) {
return json.type || "rich";
}
generateHTML() {
switch (this.type) {
case "rich":
return this.generateRich();
case "image":
return this.generateImage();
case "link":
return this.generateLink();
case "article":
return this.generateArticle();
default:
console.warn(`unsupported embed type ${this.type}, please add support dev :3`, this.json);
return document.createElement("div"); //prevent errors by giving blank div
}
}
generateRich() {
console.log(this.json);
const div = document.createElement("div");
if (this.json.color) {
div.style.backgroundColor = "#" + this.json.color.toString(16);
}
div.classList.add("embed-color");
const embed = document.createElement("div");
embed.classList.add("embed");
div.append(embed);
if (this.json.author) {
const authorline = document.createElement("div");
if (this.json.author.icon_url) {
const img = document.createElement("img");
img.classList.add("embedimg");
img.src = this.json.author.icon_url;
authorline.append(img);
}
const a = document.createElement("a");
a.innerText = this.json.author.name;
if (this.json.author.url) {
a.href = this.json.author.url;
}
a.classList.add("username");
authorline.append(a);
embed.append(authorline);
}
const title = document.createElement("a");
title.textContent = this.json.title;
if (this.json.url) {
title.href = this.json.url;
}
title.classList.add("embedtitle");
embed.append(title);
if (this.json.description) {
const p = document.createElement("p");
p.textContent = this.json.description;
embed.append(p);
}
embed.append(document.createElement("br"));
if (this.json.fields) {
for (const thing of this.json.fields) {
const div = document.createElement("div");
const b = document.createElement("b");
b.textContent = thing.name;
div.append(b);
let p;
p = document.createElement("p");
p.textContent = thing.value;
p.classList.add("embedp");
div.append(p);
if (thing.inline) {
div.classList.add("inline");
}
embed.append(div);
}
}
if (this.json.footer || this.json.timestamp) {
const footer = document.createElement("div");
if (this.json?.footer?.icon_url) {
const img = document.createElement("img");
img.src = this.json.footer.icon_url;
img.classList.add("embedicon");
footer.append(img);
}
if (this.json?.footer?.text) {
const span = document.createElement("span");
span.textContent = this.json.footer.text;
span.classList.add("spaceright");
footer.append(span);
}
if (this.json?.footer && this.json?.timestamp) {
const span = document.createElement("span");
span.textContent = "•";
span.classList.add("spaceright");
footer.append(span);
}
if (this.json?.timestamp) {
const span = document.createElement("span");
span.textContent = new Date(this.json.timestamp).toLocaleString();
;
footer.append(span);
}
embed.append(footer);
}
return div;
}
generateImage() {
const img = document.createElement("img");
img.classList.add("messageimg");
img.onclick = function () {
const full = new Fullscreen(["img", img.src, ["fit"]]);
full.show();
};
img.src = this.json.thumbnail.proxy_url;
return img;
}
generateLink() {
const table = document.createElement("table");
table.classList.add("embed", "linkembed");
const trtop = document.createElement("tr");
table.append(trtop);
{
const td = document.createElement("td");
const a = document.createElement("a");
a.href = this.json.url;
a.textContent = this.json.title;
td.append(a);
trtop.append(td);
}
{
const td = document.createElement("td");
const img = document.createElement("img");
if (this.json.thumbnail) {
img.classList.add("embedimg");
img.onclick = function () {
const full = new Fullscreen(["img", img.src, ["fit"]]);
full.show();
};
img.src = this.json.thumbnail.proxy_url;
td.append(img);
}
trtop.append(td);
}
const bottomtr = document.createElement("tr");
const td = document.createElement("td");
const span = document.createElement("span");
span.textContent = this.json.description;
td.append(span);
bottomtr.append(td);
table.append(bottomtr);
return table;
}
generateArticle() {
const colordiv = document.createElement("div");
colordiv.style.backgroundColor = "#000000";
colordiv.classList.add("embed-color");
const div = document.createElement("div");
div.classList.add("embed");
if (this.json.provider) {
const providor = document.createElement("p");
providor.classList.add("provider");
providor.textContent = this.json.provider.name;
div.append(providor);
}
const a = document.createElement("a");
a.href = this.json.url;
a.textContent = this.json.title;
div.append(a);
const description = document.createElement("p");
description.textContent = this.json.description;
div.append(description);
{
const img = document.createElement("img");
img.classList.add("bigembedimg");
img.onclick = function () {
const full = new Fullscreen(["img", img.src, ["fit"]]);
full.show();
};
img.src = this.json.thumbnail.proxy_url;
div.append(img);
}
colordiv.append(div);
return colordiv;
}
}
export { Embed };

247
.dist/fullscreen.js Normal file
View file

@ -0,0 +1,247 @@
export { Fullscreen };
class Fullscreen {
layout;
onclose;
onopen;
html;
background;
constructor(layout, onclose = _ => { }, onopen = _ => { }) {
this.layout = layout;
this.onclose = onclose;
this.onopen = onopen;
const div = document.createElement("div");
div.appendChild(this.tohtml(layout));
this.html = div;
this.html.classList.add("centeritem");
if (!(layout[0] === "img")) {
this.html.classList.add("nonimagecenter");
}
}
tohtml(array) {
switch (array[0]) {
case "img":
const img = document.createElement("img");
img.src = array[1];
if (array[2] != undefined) {
if (array[2].length == 2) {
img.width = array[2][0];
img.height = array[2][1];
}
else if (array[2][0] == "fit") {
img.classList.add("imgfit");
}
}
return img;
case "hdiv":
const hdiv = document.createElement("table");
const tr = document.createElement("tr");
hdiv.appendChild(tr);
for (const thing of array) {
if (thing === "hdiv") {
continue;
}
const td = document.createElement("td");
td.appendChild(this.tohtml(thing));
tr.appendChild(td);
}
return hdiv;
case "vdiv":
const vdiv = document.createElement("table");
for (const thing of array) {
if (thing === "vdiv") {
continue;
}
const tr = document.createElement("tr");
tr.appendChild(this.tohtml(thing));
vdiv.appendChild(tr);
}
return vdiv;
case "checkbox":
{
const div = document.createElement("div");
const checkbox = document.createElement('input');
div.appendChild(checkbox);
const label = document.createElement("span");
checkbox.value = array[2];
label.textContent = array[1];
div.appendChild(label);
checkbox.addEventListener("change", array[3]);
checkbox.type = "checkbox";
return div;
}
case "button":
{
const div = document.createElement("div");
const input = document.createElement('button');
const label = document.createElement("span");
input.textContent = array[2];
label.textContent = array[1];
div.appendChild(label);
div.appendChild(input);
input.addEventListener("click", array[3]);
return div;
}
case "mdbox":
{
const div = document.createElement("div");
const input = document.createElement("textarea");
input.value = array[2];
const label = document.createElement("span");
label.textContent = array[1];
input.addEventListener("input", array[3]);
div.appendChild(label);
div.appendChild(document.createElement("br"));
div.appendChild(input);
return div;
}
case "textbox":
{
const div = document.createElement("div");
const input = document.createElement("input");
input.value = array[2];
input.type = "text";
const label = document.createElement("span");
label.textContent = array[1];
console.log(array[3]);
input.addEventListener("input", array[3]);
div.appendChild(label);
div.appendChild(input);
return div;
}
case "fileupload":
{
const div = document.createElement("div");
const input = document.createElement("input");
input.type = "file";
const label = document.createElement("span");
label.textContent = array[1];
div.appendChild(label);
div.appendChild(input);
input.addEventListener("change", array[2]);
console.log(array);
return div;
}
case "text": {
const span = document.createElement("span");
span.textContent = array[1];
return span;
}
case "title": {
const span = document.createElement("span");
span.classList.add("title");
span.textContent = array[1];
return span;
}
case "radio": {
const div = document.createElement("div");
const fieldset = document.createElement("fieldset");
fieldset.addEventListener("change", function () {
let i = -1;
for (const thing of fieldset.children) {
i++;
if (i === 0) {
continue;
}
const checkbox = thing.children[0].children[0];
if (checkbox.checked) {
array[3](checkbox.value);
}
}
});
const legend = document.createElement("legend");
legend.textContent = array[1];
fieldset.appendChild(legend);
let i = 0;
for (const thing of array[2]) {
const div = document.createElement("div");
const input = document.createElement("input");
input.classList.add("radio");
input.type = "radio";
input.name = array[1];
input.value = thing;
if (i === array[4]) {
input.checked = true;
}
const label = document.createElement("label");
label.appendChild(input);
const span = document.createElement("span");
span.textContent = thing;
label.appendChild(span);
div.appendChild(label);
fieldset.appendChild(div);
i++;
}
div.appendChild(fieldset);
return div;
}
case "html": {
return array[1];
}
case "select": {
const div = document.createElement("div");
const label = document.createElement("label");
const select = document.createElement("select");
label.textContent = array[1];
div.append(label);
div.appendChild(select);
for (const thing of array[2]) {
const option = document.createElement("option");
option.textContent = thing;
select.appendChild(option);
}
select.selectedIndex = array[4];
select.addEventListener("change", array[3]);
return div;
}
case "tabs": {
const table = document.createElement("table");
const tabs = document.createElement("tr");
tabs.classList.add("tabbed-head");
table.appendChild(tabs);
const td = document.createElement("td");
tabs.appendChild(td);
const content = document.createElement("tr");
content.classList.add("tabbed-content");
table.appendChild(content);
let shown;
for (const thing of array[1]) {
const button = document.createElement("button");
button.textContent = thing[0];
td.appendChild(button);
const tdcontent = document.createElement("td");
tdcontent.colSpan = array[1].length;
tdcontent.appendChild(this.tohtml(thing[1]));
content.appendChild(tdcontent);
if (!shown) {
shown = tdcontent;
}
else {
tdcontent.hidden = true;
}
button.addEventListener("click", _ => {
shown.hidden = true;
tdcontent.hidden = false;
shown = tdcontent;
});
}
return table;
}
default:
console.error("can't find element:" + array[0], " full element:" + array);
return;
}
}
show() {
this.onopen();
console.log("fullscreen");
this.background = document.createElement("div");
this.background.classList.add("background");
document.body.appendChild(this.background);
document.body.appendChild(this.html);
this.background.onclick = function () { this.hide(); }.bind(this);
}
hide() {
document.body.removeChild(this.background);
document.body.removeChild(this.html);
}
}

496
.dist/guild.js Normal file
View file

@ -0,0 +1,496 @@
import { Channel } from "./channel.js";
import { Contextmenu } from "./contextmenu.js";
import { Role } from "./role.js";
import { Fullscreen } from "./fullscreen.js";
class Guild {
owner;
headers;
channels;
channelids;
id;
properties;
roles;
roleids;
prevchannel;
message_notifications;
headchannels;
position;
parent_id;
member;
html;
static contextmenu = new Contextmenu("guild menu");
static setupcontextmenu() {
Guild.contextmenu.addbutton("Copy Guild id", function () {
console.log(this);
navigator.clipboard.writeText(this.id);
});
Guild.contextmenu.addbutton("Mark as read", function () {
console.log(this);
this.markAsRead();
});
Guild.contextmenu.addbutton("Notifications", function () {
console.log(this);
this.setnotifcation();
});
Guild.contextmenu.addbutton("Leave guild", function () {
this.confirmleave();
}, null, function (_) { return _.properties.owner_id !== _.member.user.id; });
Guild.contextmenu.addbutton("Delete guild", function () {
this.confirmDelete();
}, null, function (_) { return _.properties.owner_id === _.member.user.id; });
Guild.contextmenu.addbutton("Create invite", function () {
console.log(this);
}, null, _ => true, _ => false);
/* -----things left for later-----
guild.contextmenu.addbutton("Leave Guild",function(){
console.log(this)
this.deleteChannel();
},null,_=>{return thisuser.isAdmin()})
guild.contextmenu.addbutton("Mute Guild",function(){
editchannelf(this);
},null,_=>{return thisuser.isAdmin()})
*/
}
constructor(JSON, owner) {
if (JSON === -1) {
return;
}
this.owner = owner;
this.headers = this.owner.headers;
if (!this.owner) {
console.error("localuser was not included, please fix");
}
this.channels = [];
this.channelids = {};
this.id = JSON.id;
this.properties = JSON.properties;
this.roles = [];
this.roleids = {};
this.prevchannel = undefined;
this.message_notifications = 0;
for (const roley of JSON.roles) {
const roleh = new Role(roley, this);
this.roles.push(roleh);
this.roleids[roleh.id] = roleh;
}
for (const thing of JSON.channels) {
const temp = new Channel(thing, this);
this.channels.push(temp);
this.channelids[temp.id] = temp;
}
this.headchannels = [];
for (const thing of this.channels) {
if (thing.resolveparent(this)) {
this.headchannels.push(thing);
}
}
}
notisetting(settings) {
this.message_notifications = settings.message_notifications;
}
setnotifcation() {
let noti = this.message_notifications;
const notiselect = new Fullscreen(["vdiv",
["radio", "select notifications type",
["all", "only mentions", "none"],
function (e) {
noti = ["all", "only mentions", "none"].indexOf(e);
},
noti
],
["button", "", "submit", _ => {
fetch(this.info.api.toString() + "/v9/users/@me/guilds/settings", {
method: "PATCH",
headers: this.headers,
body: JSON.stringify({
"guilds": {
[this.id]: {
"message_notifications": noti
}
}
})
});
this.message_notifications = noti;
}]
]);
notiselect.show();
}
confirmleave() {
const full = new Fullscreen([
"vdiv",
["title",
"Are you sure you want to leave?"
],
["hdiv",
["button",
"",
"Yes, I'm sure",
_ => {
this.leave().then(_ => {
full.hide();
});
}
],
["button",
"",
"Nevermind",
_ => {
full.hide();
}
]
]
]);
full.show();
}
async leave() {
return fetch(this.info.api.toString() + "/users/@me/guilds/" + this.id, {
method: "DELETE",
headers: this.headers
});
}
printServers() {
let build = "";
for (const thing of this.headchannels) {
build += (thing.name + ":" + thing.position) + "\n";
for (const thingy of thing.children) {
build += (" " + thingy.name + ":" + thingy.position) + "\n";
}
}
console.log(build);
}
calculateReorder() {
let position = -1;
let build = [];
for (const thing of this.headchannels) {
const thisthing = { id: thing.id, position: undefined, parent_id: undefined };
if (thing.position <= position) {
thing.position = (thisthing.position = position + 1);
}
position = thing.position;
console.log(position);
if (thing.move_id && thing.move_id !== thing.parent_id) {
thing.parent_id = thing.move_id;
thisthing.parent_id = thing.parent_id;
thing.move_id = undefined;
}
if (thisthing.position || thisthing.parent_id) {
build.push(thisthing);
console.log(this.channelids[thisthing.parent_id]);
}
if (thing.children.length > 0) {
const things = thing.calculateReorder();
for (const thing of things) {
build.push(thing);
}
}
}
console.log(build);
this.printServers();
if (build.length === 0) {
return;
}
const serverbug = false;
if (serverbug) {
for (const thing of build) {
console.log(build, thing);
fetch(this.info.api.toString() + "/v9/guilds/" + this.id + "/channels", {
method: "PATCH",
headers: this.headers,
body: JSON.stringify([thing])
});
}
}
else {
fetch(this.info.api.toString() + "/v9/guilds/" + this.id + "/channels", {
method: "PATCH",
headers: this.headers,
body: JSON.stringify(build)
});
}
}
get localuser() {
return this.owner;
}
get info() {
return this.owner.info;
}
sortchannels() {
this.headchannels.sort((a, b) => { return a.position - b.position; });
}
generateGuildIcon() {
const divy = document.createElement("div");
divy.classList.add("servernoti");
const noti = document.createElement("div");
noti.classList.add("unread");
divy.append(noti);
this.localuser.guildhtml[this.id] = divy;
if (this.properties.icon != null) {
const img = document.createElement("img");
img.classList.add("pfp", "servericon");
img.src = this.info.cdn.toString() + "icons/" + this.properties.id + "/" + this.properties.icon + ".png";
divy.appendChild(img);
img.onclick = () => {
console.log(this.loadGuild);
this.loadGuild();
this.loadChannel();
};
Guild.contextmenu.bind(img, this);
}
else {
const div = document.createElement("div");
let build = "";
for (const char of this.properties.name.split(" ")) {
build += char[0];
}
div.textContent = build;
div.classList.add("blankserver", "servericon");
divy.appendChild(div);
div.onclick = () => {
this.loadGuild();
this.loadChannel();
};
Guild.contextmenu.bind(div, this);
}
return divy;
}
confirmDelete() {
let confirmname = "";
const full = new Fullscreen([
"vdiv",
["title",
"Are you sure you want to delete " + this.properties.name + "?"
],
["textbox",
"Name of server:",
"",
function () {
confirmname = this.value;
}
],
["hdiv",
["button",
"",
"Yes, I'm sure",
_ => {
console.log(confirmname);
if (confirmname !== this.properties.name) {
return;
}
this.delete().then(_ => {
full.hide();
});
}
],
["button",
"",
"Nevermind",
_ => {
full.hide();
}
]
]
]);
full.show();
}
async delete() {
return fetch(this.info.api.toString() + "/guilds/" + this.id + "/delete", {
method: "POST",
headers: this.headers,
});
}
unreads(html = undefined) {
if (html) {
this.html = html;
}
else {
html = this.html;
}
let read = true;
for (const thing of this.channels) {
if (thing.hasunreads) {
console.log(thing);
read = false;
break;
}
}
if (!html) {
return;
}
if (read) {
html.children[0].classList.remove("notiunread");
}
else {
html.children[0].classList.add("notiunread");
}
}
getHTML() {
//this.printServers();
this.sortchannels();
this.printServers();
const build = document.createElement("div");
for (const thing of this.headchannels) {
build.appendChild(thing.createguildHTML(this.isAdmin()));
}
return build;
}
isAdmin() {
return this.member.isAdmin();
}
async markAsRead() {
const build = { read_states: [] };
for (const thing of this.channels) {
if (thing.hasunreads) {
build.read_states.push({ channel_id: thing.id, message_id: thing.lastmessageid, read_state_type: 0 });
thing.lastreadmessageid = thing.lastmessageid;
thing.myhtml.classList.remove("cunread");
}
}
this.unreads();
fetch(this.info.api.toString() + "/v9/read-states/ack-bulk", {
method: "POST",
headers: this.headers,
body: JSON.stringify(build)
});
}
fillMember(member) {
const realroles = [];
for (const thing of member.roles) {
realroles.push(this.getRole(thing));
}
member.roles = realroles;
return member;
}
giveMember(member) {
this.fillMember(member);
this.member = member;
}
getRole(ID) {
return this.roleids[ID];
}
hasRole(r) {
console.log("this should run");
if ((typeof r) !== (typeof "")) {
r = r.id;
}
return this.member.hasRole(r);
}
loadChannel(ID = undefined) {
if (ID && this.channelids[ID]) {
this.channelids[ID].getHTML();
return;
}
if (this.prevchannel) {
console.log(this.prevchannel);
this.prevchannel.getHTML();
return;
}
for (const thing of this.channels) {
if (thing.children.length === 0) {
thing.getHTML();
return;
}
}
}
loadGuild() {
this.localuser.loadGuild(this.id);
}
updateChannel(JSON) {
this.channelids[JSON.id].updateChannel(JSON);
this.headchannels = [];
for (const thing of this.channels) {
thing.children = [];
}
for (const thing of this.channels) {
if (thing.resolveparent(this)) {
this.headchannels.push(thing);
}
}
this.printServers();
}
createChannelpac(JSON) {
const thischannel = new Channel(JSON, this);
this.channelids[JSON.id] = thischannel;
this.channels.push(thischannel);
thischannel.resolveparent(this);
if (!thischannel.parrent) {
this.headchannels.push(thischannel);
}
this.calculateReorder();
this.printServers();
}
createchannels(func = this.createChannel) {
let name = "";
let category = 0;
const channelselect = new Fullscreen(["vdiv",
["radio", "select channel type",
["voice", "text", "announcement"],
function (e) {
console.log(e);
category = { "text": 0, "voice": 2, "announcement": 5, "category": 4 }[e];
},
1
],
["textbox", "Name of channel", "", function () {
console.log(this);
name = this.value;
}],
["button", "", "submit", function () {
console.log(name, category);
func(name, category);
channelselect.hide();
}.bind(this)]
]);
channelselect.show();
}
createcategory() {
let name = "";
let category = 4;
const channelselect = new Fullscreen(["vdiv",
["textbox", "Name of category", "", function () {
console.log(this);
name = this.value;
}],
["button", "", "submit", function () {
console.log(name, category);
this.createChannel(name, category);
channelselect.hide();
}]
]);
channelselect.show();
}
delChannel(JSON) {
const channel = this.channelids[JSON.id];
delete this.channelids[JSON.id];
this.channels.splice(this.channels.indexOf(channel), 1);
const indexy = this.headchannels.indexOf(channel);
if (indexy !== -1) {
this.headchannels.splice(indexy, 1);
}
/*
const build=[];
for(const thing of this.channels){
console.log(thing.id);
if(thing!==channel){
build.push(thing)
}else{
console.log("fail");
if(thing.parrent){
thing.parrent.delChannel(JSON);
}
}
}
this.channels=build;
*/
this.printServers();
}
createChannel(name, type) {
fetch(this.info.api.toString() + "/guilds/" + this.id + "/channels", {
method: "Post",
headers: this.headers,
body: JSON.stringify({ name: name, type: type })
});
}
}
Guild.setupcontextmenu();
export { Guild };

276
.dist/index.js Normal file
View file

@ -0,0 +1,276 @@
import { Localuser } from "./localuser.js";
import { Contextmenu } from "./contextmenu.js";
import { mobile, getBulkUsers, setTheme } from "./login.js";
async function waitforload() {
let res;
new Promise(r => { res = r; });
document.addEventListener("DOMContentLoaded", function () {
res();
});
await res;
}
await waitforload();
function setDynamicHeight() {
var servertdHeight = document.getElementById('servertd').offsetHeight + document.getElementById('typebox').offsetHeight + document.getElementById('pasteimage').offsetHeight;
document.documentElement.style.setProperty('--servertd-height', servertdHeight + 'px');
}
const resizeObserver = new ResizeObserver(() => {
setDynamicHeight();
});
resizeObserver.observe(document.getElementById('servertd'));
resizeObserver.observe(document.getElementById('typebox'));
resizeObserver.observe(document.getElementById('pasteimage'));
setDynamicHeight();
const users = getBulkUsers();
if (!users.currentuser) {
window.location.href = '/login.html';
}
var info = users.users[users.currentuser].serverurls;
let token = users.users[users.currentuser].token;
let READY;
let thisuser = new Localuser(users.users[users.currentuser]);
thisuser.initwebsocket().then(_ => {
thisuser.loaduser();
thisuser.init();
document.getElementById("loading").classList.add("doneloading");
document.getElementById("loading").classList.remove("loading");
console.log("done loading");
});
{
const userinfo = document.getElementById("userinfo");
const userdock = document.getElementById("userdock");
userinfo.addEventListener("click", function (event) {
const table = document.createElement("table");
for (const thing of Object.values(users.users)) {
const specialuser = thing;
console.log(specialuser.pfpsrc);
const tr = document.createElement("tr");
const td = document.createElement("td");
const userinfo = document.createElement("table");
userinfo.classList.add("switchtable");
const row = document.createElement("tr");
userinfo.append(row);
const pfpcell = document.createElement("td");
row.append(pfpcell);
const pfp = document.createElement("img");
pfpcell.append(pfp);
const usertd = document.createElement("td");
row.append(usertd);
const user = document.createElement("div");
usertd.append(user);
user.append(specialuser.username);
user.append(document.createElement("br"));
const span = document.createElement("span");
span.textContent = specialuser.serverurls.wellknown.hostname;
user.append(span);
span.classList.add("serverURL");
pfp.src = specialuser.pfpsrc;
pfp.classList.add("pfp");
td.append(userinfo);
tr.append(td);
table.append(tr);
tr.addEventListener("click", _ => {
thisuser.unload();
document.getElementById("loading").classList.remove("doneloading");
document.getElementById("loading").classList.add("loading");
thisuser = new Localuser(specialuser);
users["currentuser"] = specialuser.uid;
localStorage.setItem("userinfos", JSON.stringify(users));
thisuser.initwebsocket().then(_ => {
thisuser.loaduser();
thisuser.init();
document.getElementById("loading").classList.add("doneloading");
document.getElementById("loading").classList.remove("loading");
console.log("done loading");
});
});
}
{
const tr = document.createElement("tr");
const td = document.createElement("td");
tr.append(td);
td.append("Switch accounts ⇌");
td.addEventListener("click", _ => {
window.location.href = "/login.html";
});
table.append(tr);
}
table.classList.add("accountSwitcher");
if (Contextmenu.currentmenu != "") {
Contextmenu.currentmenu.remove();
}
Contextmenu.currentmenu = table;
console.log(table);
userdock.append(table);
event.stopImmediatePropagation();
});
}
{
const menu = new Contextmenu("create rightclick");
menu.addbutton("Create channel", function () {
thisuser.lookingguild.createchannels();
}, null, _ => { return thisuser.isAdmin(); });
menu.addbutton("Create category", function () {
thisuser.lookingguild.createcategory();
}, null, _ => { return thisuser.isAdmin(); });
menu.bind(document.getElementById("channels"));
}
function editchannelf(channel) { channel.editChannel(); }
const pasteimage = document.getElementById("pasteimage");
let replyingto = null;
async function enter(event) {
const channel = thisuser.channelfocus;
channel.typingstart();
if (event.key === "Enter" && !event.shiftKey) {
event.preventDefault();
if (channel.editing) {
channel.editing.edit((typebox).value);
channel.editing = null;
}
else {
let replying = replyingto?.all;
if (replyingto) {
replyingto.classList.remove("replying");
}
replyingto = false;
channel.sendMessage(typebox.value, {
attachments: images,
replyingto: replying,
});
}
while (images.length != 0) {
images.pop();
pasteimage.removeChild(imageshtml.pop());
}
typebox.value = "";
return;
}
}
const typebox = document.getElementById("typebox");
typebox.addEventListener("keyup", enter);
typebox.addEventListener("keydown", event => {
if (event.key === "Enter" && !event.shiftKey)
event.preventDefault();
});
console.log(typebox);
typebox.onclick = console.log;
let serverz = 0;
let serverid = [];
let cchanel = 0;
function getguildinfo() {
const path = window.location.pathname.split("/");
const channel = path[3];
this.ws.send(JSON.stringify({ op: 14, d: { guild_id: path[2], channels: { [channel]: [[0, 99]] } } }));
}
const images = [];
const imageshtml = [];
function createunknown(fname, fsize) {
const div = document.createElement("table");
div.classList.add("unknownfile");
const nametr = document.createElement("tr");
div.append(nametr);
const fileicon = document.createElement("td");
nametr.append(fileicon);
fileicon.append("🗎");
fileicon.classList.add("fileicon");
fileicon.rowSpan = 2;
const nametd = document.createElement("td");
{
nametd.textContent = fname;
}
nametd.classList.add("filename");
nametr.append(nametd);
const sizetr = document.createElement("tr");
const size = document.createElement("td");
sizetr.append(size);
size.textContent = "Size:" + filesizehuman(fsize);
size.classList.add("filesize");
div.appendChild(sizetr);
return div;
}
function filesizehuman(fsize) {
var i = fsize == 0 ? 0 : Math.floor(Math.log(fsize) / Math.log(1024));
return +((fsize / Math.pow(1024, i)).toFixed(2)) * 1 + ' ' + ['Bytes', 'Kilobytes', 'Megabytes', 'Gigabytes', 'Terabytes'][i];
}
function createunknownfile(file) {
return createunknown(file.name, file.size);
}
function filetohtml(file) {
if (file.type.startsWith('image/')) {
const img = document.createElement('img');
const blob = URL.createObjectURL(file);
img.src = blob;
return img;
}
else {
console.log(file.name);
return createunknownfile(file);
}
}
document.addEventListener('paste', async (e) => {
Array.from(e.clipboardData.files).forEach(async (file) => {
e.preventDefault();
const html = filetohtml(file);
pasteimage.appendChild(html);
const blob = URL.createObjectURL(file);
images.push(file);
imageshtml.push(html);
console.log(file.type);
});
});
setTheme();
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();
}
}
//
});
if (mobile) {
document.getElementById("channelw").onclick = function () {
document.getElementById("channels").parentNode.classList.add("collapse");
document.getElementById("servertd").classList.add("collapse");
document.getElementById("servers").classList.add("collapse");
};
document.getElementById("mobileback").textContent = "#";
document.getElementById("mobileback").onclick = function () {
document.getElementById("channels").parentNode.classList.remove("collapse");
document.getElementById("servertd").classList.remove("collapse");
document.getElementById("servers").classList.remove("collapse");
};
}
/*
{
const messages=document.getElementById("messages");
let height=messages.clientHeight;
//
const resizeObserver=new ResizeObserver(()=>{
console.log(messages.scrollTop,messages.clientHeight-height-messages.scrollHeight);
messages.scrollTop-=height-messages.scrollHeight;
console.log(messages.scrollTop)
//if(shouldsnap){
// document.getElementById("messagecontainer").scrollTop = document.getElementById("messagecontainer").scrollHeight;
//}
height=messages.scrollHeight;
})
resizeObserver.observe(messages)
}
*/

555
.dist/localuser.js Normal file
View file

@ -0,0 +1,555 @@
import { Guild } from "./guild.js";
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 { Fullscreen } from "./fullscreen.js";
import { setTheme } from "./login.js";
class Localuser {
packets;
token;
userinfo;
serverurls;
initialized;
info;
headers;
usersettings;
ready;
guilds;
guildids;
user;
status;
channelfocus;
lookingguild;
guildhtml;
ws;
typing;
wsinterval;
constructor(userinfo) {
this.packets = 1;
this.token = userinfo.token;
this.userinfo = userinfo;
this.serverurls = this.userinfo.serverurls;
this.initialized = false;
this.info = this.serverurls;
this.headers = { "Content-type": "application/json; charset=UTF-8", Authorization: this.userinfo.token };
}
gottenReady(ready) {
this.usersettings = null;
this.initialized = true;
this.ready = ready;
this.guilds = [];
this.guildids = {};
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 = {};
for (const thing of ready.d.guilds) {
const temp = new Guild(thing, this);
this.guilds.push(temp);
this.guildids[temp.id] = temp;
}
{
const temp = new Direct(ready.d.private_channels, this);
this.guilds.push(temp);
this.guildids[temp.id] = temp;
}
console.log(ready.d.user_guild_settings.entries);
for (const thing of ready.d.user_guild_settings.entries) {
this.guildids[thing.guild_id].notisetting(thing);
}
for (const thing of ready.d.merged_members) {
const guild = this.guildids[thing[0].guild_id];
const temp = new Member(thing[0], guild);
guild.giveMember(temp);
}
for (const thing of ready.d.read_state.entries) {
const guild = this.resolveChannelFromID(thing.id).guild;
if (guild === undefined) {
continue;
}
const guildid = guild.id;
this.guildids[guildid].channelids[thing.channel_id].readStateInfo(thing);
}
this.typing = [];
}
outoffocus() {
document.getElementById("servers").textContent = "";
document.getElementById("channels").textContent = "";
document.getElementById("messages").textContent = "";
this.lookingguild = null;
this.channelfocus = null;
}
unload() {
this.initialized = false;
clearInterval(this.wsinterval);
this.outoffocus();
this.guilds = [];
this.guildids = {};
this.ws.close(4000);
}
async initwebsocket() {
let returny = null;
const promise = new Promise((res) => { returny = res; });
this.ws = new WebSocket(this.serverurls.gateway.toString());
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,
"release_channel": "Custom",
"browser_user_agent": navigator.userAgent
},
"compress": false,
"presence": {
"status": "online",
"since": new Date().getTime(),
"activities": [],
"afk": false
}
}
}));
});
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);
}
break;
case "READY":
this.gottenReady(temp);
this.genusersettings();
returny();
break;
case "MESSAGE_UPDATE":
if (this.initialized) {
if (this.channelfocus.id === temp.d.channel_id) {
const find = temp.d.id;
const messagelist = document.getElementById("messages").children;
for (const message of messagelist) {
const all = message["all"];
if (all.id === find) {
all.content = temp.d.content;
message["txt"].innerHTML = markdown(temp.d.content).innerHTML;
break;
}
}
}
else {
this.resolveChannelFromID(temp.d.channel_id).messages.find(e => e.id === temp.d.channel_id).content = temp.d.content;
}
}
break;
case "TYPING_START":
if (this.initialized) {
this.typeingStart(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.guilds.push(guildy);
this.guildids[guildy.id] = guildy;
document.getElementById("servers").insertBefore(guildy.generateGuildIcon(), document.getElementById("bottomseperator"));
}
}
}
else if (temp.op === 10) {
console.log("heartbeat down");
this.wsinterval = setInterval(_ => {
this.ws.send(JSON.stringify({ op: 1, d: this.packets }));
}, temp.d.heartbeat_interval);
this.packets = 1;
}
else if (temp.op != 11) {
this.packets++;
}
}
catch (error) {
console.error(error);
}
});
this.ws.addEventListener('close', (event) => {
clearInterval(this.wsinterval);
console.log('WebSocket closed');
console.warn(event);
if (event.code !== 4000 && this === this) {
this.unload();
document.getElementById("loading").classList.remove("doneloading");
document.getElementById("loading").classList.add("loading");
this.initwebsocket().then(_ => {
this.loaduser();
this.init();
document.getElementById("loading").classList.add("doneloading");
document.getElementById("loading").classList.remove("loading");
console.log("done loading");
});
}
});
await promise;
return;
}
resolveChannelFromID(ID) {
console.log(this.guilds.find(guild => guild.channelids[ID]).channelids);
let resolve = this.guilds.find(guild => guild.channelids[ID]).channelids[ID];
resolve ??= undefined;
return resolve;
}
updateChannel(JSON) {
this.guildids[JSON.guild_id].updateChannel(JSON);
if (JSON.guild_id === this.lookingguild.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) {
this.loadGuild(JSON.guild_id);
}
}
delChannel(JSON) {
JSON.guild_id ??= "@me";
this.guildids[JSON.guild_id].delChannel(JSON);
if (JSON.guild_id === this.lookingguild.id) {
this.loadGuild(JSON.guild_id);
}
}
init() {
const location = window.location.href.split("/");
if (location[3] === "channels") {
const guild = this.loadGuild(location[4]);
guild.loadChannel(location[5]);
this.channelfocus = guild.channelids[location[5]];
}
this.buildservers();
}
loaduser() {
document.getElementById("username").textContent = this.user.username;
document.getElementById("userpfp").src = this.user.getpfpsrc();
document.getElementById("status").textContent = this.status;
}
isAdmin() {
return this.lookingguild.isAdmin();
}
loadGuild(id) {
let guild = this.guildids[id];
if (!guild) {
guild = this.guildids["@me"];
}
this.lookingguild = guild;
document.getElementById("serverName").textContent = guild.properties.name;
//console.log(this.guildids,id)
document.getElementById("channels").innerHTML = "";
document.getElementById("channels").appendChild(guild.getHTML());
return guild;
}
buildservers() {
const serverlist = document.getElementById("servers"); //
const div = document.createElement("div");
div.textContent = "⌂";
div.classList.add("home", "servericon");
div["all"] = this.guildids["@me"];
serverlist.appendChild(div);
div.onclick = function () {
this["all"].loadGuild();
this["all"].loadChannel();
};
const sentdms = document.createElement("div");
sentdms.classList.add("sentdms");
serverlist.append(sentdms);
sentdms.id = "sentdms";
const br = document.createElement("hr");
br.classList.add("lightbr");
serverlist.appendChild(br);
for (const thing of this.guilds) {
if (thing instanceof Direct) {
thing.unreaddms();
continue;
}
const divy = thing.generateGuildIcon();
serverlist.append(divy);
}
{
const br = document.createElement("hr");
br.classList.add("lightbr");
serverlist.appendChild(br);
br.id = "bottomseperator";
const div = document.createElement("div");
div.textContent = "+";
div.classList.add("addserver", "servericon");
serverlist.appendChild(div);
div.onclick = _ => {
console.log("clicked :3");
this.createGuild();
};
}
this.unreads();
}
createGuild() {
let inviteurl = "";
const error = document.createElement("span");
const full = new Fullscreen(["tabs", [
["Join using invite", [
"vdiv",
["textbox",
"Invite Link/Code",
"",
function () {
console.log(this);
inviteurl = this.value;
}
],
["html", error],
["button",
"",
"Submit",
_ => {
let parsed = "";
if (inviteurl.includes("/")) {
parsed = inviteurl.split("/")[inviteurl.split("/").length - 1];
}
else {
parsed = inviteurl;
}
fetch(this.info.api.toString() + "/v9/invites/" + parsed, {
method: "POST",
headers: this.headers,
}).then(r => r.json()).then(_ => {
console.log(_);
if (_.message) {
error.textContent = _.message;
}
});
}
]
]],
["Create Server", [
"text", "Not currently implemented, sorry"
]]
]]);
full.show();
}
messageCreate(messagep) {
messagep.d.guild_id ??= "@me";
this.guildids[messagep.d.guild_id].channelids[messagep.d.channel_id].messageCreate(messagep);
this.unreads();
}
unreads() {
console.log(this.guildhtml);
for (const thing of this.guilds) {
if (thing.id === "@me") {
continue;
}
thing.unreads(this.guildhtml[thing.id]);
}
}
typeingStart(typing) {
if (this.channelfocus.id === typing.d.channel_id) {
const memb = typing.d.member;
let name;
if (memb.id === this.user.id) {
console.log("you is typing");
return;
}
console.log("user is typing and you should see it");
if (memb.nick) {
name = memb.nick;
}
else {
name = memb.user.username;
}
let already = false;
for (const thing of this.typing) {
if (thing[0] === name) {
thing[1] = new Date().getTime();
already = true;
break;
}
}
if (!already) {
this.typing.push([name, new Date().getTime()]);
}
setTimeout(this.rendertyping.bind(this), 10000);
this.rendertyping();
}
}
updatepfp(file) {
var reader = new FileReader();
reader.readAsDataURL(file);
console.log(this.headers);
reader.onload = () => {
fetch(this.info.api.toString() + "/v9/users/@me", {
method: "PATCH",
headers: this.headers,
body: JSON.stringify({
avatar: reader.result,
})
});
console.log(reader.result);
};
}
updatepronouns(pronouns) {
fetch(this.info.api.toString() + "/v9/users/@me/profile", {
method: "PATCH",
headers: this.headers,
body: JSON.stringify({
pronouns: pronouns,
})
});
}
updatebio(bio) {
fetch(this.info.api.toString() + "/v9/users/@me/profile", {
method: "PATCH",
headers: this.headers,
body: JSON.stringify({
bio: bio,
})
});
}
rendertyping() {
const typingtext = document.getElementById("typing");
let build = "";
const array2 = [];
let showing = false;
let i = 0;
for (const thing of this.typing) {
i++;
if (thing[1] > new Date().getTime() - 5000) {
build += thing[0];
array2.push(thing);
showing = true;
if (i !== this.typing.length) {
build += ",";
}
}
}
if (i > 1) {
build += " are typing";
}
else {
build += " is typing";
}
console.log(typingtext.classList);
if (showing) {
typingtext.classList.remove("hidden");
document.getElementById("typingtext").textContent = build;
}
else {
typingtext.classList.add("hidden");
}
}
genusersettings() {
const hypothetcialprofie = document.createElement("div");
let file = null;
let newprouns = null;
let newbio = null;
let hypouser = new User(this.user, this, true);
function regen() {
hypothetcialprofie.textContent = "";
const hypoprofile = hypouser.buildprofile(-1, -1);
hypothetcialprofie.appendChild(hypoprofile);
}
regen();
this.usersettings = new Fullscreen(["hdiv",
["vdiv",
["fileupload", "upload pfp:", function (e) {
console.log(this.files[0]);
file = this.files[0];
const blob = URL.createObjectURL(this.files[0]);
hypouser.avatar = blob;
hypouser.hypotheticalpfp = true;
regen();
}],
["textbox", "Pronouns:", this.user.pronouns, function (e) {
console.log(this.value);
hypouser.pronouns = this.value;
newprouns = this.value;
regen();
}],
["mdbox", "Bio:", this.user.bio, function (e) {
console.log(this.value);
hypouser.bio = this.value;
newbio = this.value;
regen();
}],
["button", "update user content:", "submit", function () {
if (file !== null) {
this.updatepfp(file);
}
if (newprouns !== null) {
this.updatepronouns(newprouns);
}
if (newbio !== null) {
this.updatebio(newbio);
}
}],
["select", "Theme:", ["Dark", "Light", "WHITE"], e => {
localStorage.setItem("theme", ["Dark", "Light", "WHITE"][e.target.selectedIndex]);
setTheme();
}, ["Dark", "Light", "WHITE"].indexOf(localStorage.getItem("theme"))],
["select", "Notification sound:", Voice.sounds, e => {
Voice.setNotificationSound(Voice.sounds[e.target.selectedIndex]);
Voice.noises(Voice.sounds[e.target.selectedIndex]);
}, Voice.sounds.indexOf(Voice.getNotificationSound())]
],
["vdiv",
["html", hypothetcialprofie]
]
], _ => { }, function () {
console.log(this);
hypouser = new User(this.user, this);
regen();
file = null;
newprouns = null;
newbio = null;
}.bind(this));
}
}
export { Localuser };

237
.dist/login.js Normal file
View file

@ -0,0 +1,237 @@
const mobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
export { mobile, getBulkUsers, getBulkInfo, setTheme, Specialuser };
function setTheme() {
const name = localStorage.getItem("theme");
if (!name) {
document.body.className = "Dark-theme";
localStorage.setItem("theme", "Dark");
}
document.body.className = name + "-theme";
}
setTheme();
function getBulkUsers() {
const json = getBulkInfo();
for (const thing in json.users) {
json.users[thing] = new Specialuser(json.users[thing]);
}
return json;
}
function getBulkInfo() {
return JSON.parse(localStorage.getItem("userinfos"));
}
function setDefaults() {
let userinfos = getBulkInfo();
if (!userinfos) {
localStorage.setItem("userinfos", JSON.stringify({
currentuser: null,
users: {},
preferances: {
theme: "Dark",
notifcations: false,
notisound: "three",
},
}));
}
if (userinfos.users === undefined) {
userinfos.users = {};
}
if (userinfos.preferances === undefined) {
userinfos.preferances = {
theme: "Dark",
notifcations: false,
notisound: "three",
};
}
if (userinfos.preferances && (userinfos.preferances.notisound === undefined)) {
userinfos.preferances.notisound = "three";
}
localStorage.setItem("userinfos", JSON.stringify(userinfos));
}
setDefaults();
class Specialuser {
serverurls;
email;
token;
loggedin;
json;
constructor(json) {
if (json instanceof Specialuser) {
console.error("specialuser can't construct from another specialuser");
}
this.serverurls = json.serverurls;
this.serverurls.api = new URL(this.serverurls.api);
this.serverurls.cdn = new URL(this.serverurls.cdn);
this.serverurls.gateway = new URL(this.serverurls.gateway);
this.serverurls.wellknown = new URL(this.serverurls.wellknown);
this.email = json.email;
this.token = json.token;
this.loggedin = json.loggedin;
this.json = json;
if (!this.serverurls || !this.email || !this.token) {
console.error("There are fundamentally missing pieces of info missing from this user");
}
}
set pfpsrc(e) {
console.log("this ran fr");
this.json.pfpsrc = e;
this.updateLocal();
}
get pfpsrc() {
return this.json.pfpsrc;
}
set username(e) {
this.json.username = e;
this.updateLocal();
}
get username() {
return this.json.username;
}
get uid() {
return this.email + this.serverurls.wellknown;
}
toJSON() {
return this.json;
}
updateLocal() {
const info = getBulkInfo();
info.users[this.uid] = this.toJSON();
localStorage.setItem("userinfos", JSON.stringify(info));
}
}
function adduser(user) {
user = new Specialuser(user);
const info = getBulkInfo();
info.users[user.uid] = user;
info.currentuser = user.uid;
localStorage.setItem("userinfos", JSON.stringify(info));
}
const instancein = document.getElementById("instancein");
let timeout;
let instanceinfo;
async function checkInstance(e) {
const verify = document.getElementById("verify");
;
try {
verify.textContent = "Checking Instance";
const instanceinfo = await setInstance(instancein.value);
localStorage.setItem("instanceinfo", JSON.stringify(instanceinfo));
verify.textContent = "Instance is all good";
if (checkInstance["alt"]) {
checkInstance["alt"]();
}
setTimeout(_ => {
console.log(verify.textContent);
verify.textContent = "";
}, 3000);
}
catch (e) {
console.log("catch");
verify.textContent = "Invalid Instance, try again";
}
}
if (instancein) {
console.log(instancein);
instancein.addEventListener("keydown", e => {
const verify = document.getElementById("verify");
verify.textContent = "Waiting to check Instance";
clearTimeout(timeout);
timeout = setTimeout(checkInstance, 1000);
});
if (localStorage.getItem("instanceinfo")) {
instancein.value = JSON.parse(localStorage.getItem("instanceinfo")).wellknown;
}
else {
checkInstance("https://spacebar.chat/");
}
}
async function login(username, password) {
const options = {
method: "POST",
body: JSON.stringify({
"login": username,
"password": password,
"undelete": false
}),
headers: {
"Content-type": "application/json; charset=UTF-8",
}
};
try {
const info = JSON.parse(localStorage.getItem("instanceinfo"));
const url = new URL(info.login);
return await fetch(url.origin + '/api/auth/login', options).then(responce => responce.json())
.then((response) => {
console.log(response, response.message);
if ("Invalid Form Body" === response.message) {
return response.errors.login._errors[0].message;
console.log("test");
}
//this.serverurls||!this.email||!this.token
adduser({ serverurls: JSON.parse(localStorage.getItem("instanceinfo")), email: username, token: response.token });
window.location.href = '/channels/@me';
return response.token;
});
}
catch (error) {
console.error('Error:', error);
}
;
}
async function setInstance(url) {
url = new URL(url);
async function attempt(aurl) {
const info = await fetch(`${aurl.toString()}${aurl.pathname.includes("api") ? "" : "api"}/policies/instance/domains`)
.then((x) => x.json());
return {
api: info.apiEndpoint,
gateway: info.gateway,
cdn: info.cdn,
wellknown: url,
login: aurl.toString()
};
}
try {
return await attempt(url);
}
catch (e) {
}
const wellKnown = await fetch(`${url.origin}/.well-known/spacebar`)
.then((x) => x.json())
.then((x) => new URL(x.api));
return await attempt(wellKnown);
}
async function check(e) {
e.preventDefault();
let h = await login(e.srcElement[1].value, e.srcElement[2].value);
document.getElementById("wrong").textContent = h;
console.log(h);
}
if (document.getElementById("form")) {
document.getElementById("form").addEventListener("submit", check);
}
//Service workers :3
if ("serviceWorker" in navigator) {
navigator.serviceWorker.register("/service.js", {
scope: "/",
}).then((registration) => {
let serviceWorker;
if (registration.installing) {
serviceWorker = registration.installing;
console.log("installing");
}
else if (registration.waiting) {
serviceWorker = registration.waiting;
console.log("waiting");
}
else if (registration.active) {
serviceWorker = registration.active;
console.log("active");
}
if (serviceWorker) {
console.log(serviceWorker.state);
serviceWorker.addEventListener("statechange", (e) => {
console.log(e.target.state);
});
}
});
}

357
.dist/markdown.js Normal file
View file

@ -0,0 +1,357 @@
export { markdown };
function markdown(text, keep = false) {
let txt;
if ((typeof txt) === "string") {
txt = text.split("");
}
else {
txt = text;
}
const span = document.createElement("span");
let current = document.createElement("span");
function appendcurrent() {
if (current.innerHTML !== "") {
span.append(current);
current = document.createElement("span");
}
}
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 + 2] === " ") {
element = document.createElement("h1");
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) {
span.appendChild(document.createElement("br"));
}
const build = [];
for (; txt[i] !== "\n" && txt[i] !== undefined; i++) {
build.push(txt[i]);
}
if (keep) {
element.append(keepys);
}
element.appendChild(markdown(build, keep));
span.append(element);
i--;
continue;
}
if (first) {
i++;
}
}
if (txt[i] === "\n") {
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 (find === count) {
appendcurrent();
i = j;
if (keep) {
build += "`".repeat(find);
}
if (count !== 3) {
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));
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));
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));
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));
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));
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));
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 underscores = "~~";
if (count === 2) {
const s = document.createElement("s");
if (keep) {
s.append(underscores);
}
s.appendChild(markdown(build, keep));
if (keep) {
s.append(underscores);
}
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 underscores = "||";
if (count === 2) {
const j = document.createElement("j");
if (keep) {
j.append(underscores);
}
j.appendChild(markdown(build, keep));
j.classList.add("spoiler");
j.onclick = markdown.unspoil;
if (keep) {
j.append(underscores);
}
span.appendChild(j);
}
continue;
}
}
current.textContent += txt[i];
}
appendcurrent();
return span;
}
markdown.unspoil = function (e) {
//console.log("undone")
e.target.classList.remove("spoiler");
e.target.classList.add("unspoiled");
};

80
.dist/member.js Normal file
View file

@ -0,0 +1,80 @@
import { User } from "./user.js";
class Member {
static already = {};
owner;
user;
roles;
constructor(memberjson, owner) {
if (!owner) {
console.error("Guild not included in the creation of a member object");
}
this.owner = owner;
let membery = memberjson;
if (memberjson.guild_member) {
membery = memberjson.guild_member;
this.user = memberjson.user;
}
for (const thing of Object.keys(membery)) {
if (thing === "guild") {
continue;
}
this[thing] = membery[thing];
}
this.user = new User(this.user, owner.localuser);
}
get guild() {
return this.owner;
}
get localuser() {
return this.guild.localuser;
}
get info() {
return this.owner.info;
}
static async resolve(user, guild) {
if (guild.id === "@me") {
return null;
}
if (!Member.already[guild.id]) {
Member.already[guild.id] = {};
}
else if (Member.already[guild.id][user.id]) {
const memb = Member.already[guild.id][user.id];
if (memb instanceof Promise) {
return await memb;
}
return memb;
}
const promoise = fetch(guild.info.api.toString() + "/v9/users/" + user.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][user.id] = memb;
guild.fillMember(memb);
console.log("resolved");
return memb;
});
Member.already[guild.id][user.id] = promoise;
return await promoise;
}
hasRole(ID) {
console.log(this.roles, ID);
for (const thing of this.roles) {
if (thing.id === ID) {
return true;
}
}
return false;
}
getColor() {
for (const thing of this.roles) {
const color = thing.getColor();
if (color) {
return color;
}
}
return "";
}
isAdmin() {
return this.guild.properties.owner_id === this.user.id;
}
}
export { Member };

318
.dist/message.js Normal file
View file

@ -0,0 +1,318 @@
import { Contextmenu } from "./contextmenu.js";
import { User } from "./user.js";
import { Member } from "./member.js";
import { markdown } from "./markdown.js";
import { Embed } from "./embed.js";
import { Fullscreen } from "./fullscreen.js";
class Message {
static contextmenu = new Contextmenu("message menu");
owner;
headers;
embeds;
author;
mentions;
mention_roles;
attachments;
id;
message_reference;
type;
timestamp;
content;
static setupcmenu() {
Message.contextmenu.addbutton("Copy raw text", function () {
navigator.clipboard.writeText(this.content);
});
Message.contextmenu.addbutton("Reply", function (div) {
if (this.channel.replyingto) {
this.channel.replyingto.classList.remove("replying");
}
this.channel.replyingto = div;
console.log(div);
this.channel.replyingto.classList.add("replying");
});
Message.contextmenu.addbutton("Copy message id", function () {
navigator.clipboard.writeText(this.id);
});
Message.contextmenu.addbutton("Copy user id", function () {
navigator.clipboard.writeText(this.author.id);
});
Message.contextmenu.addbutton("Message user", function () {
fetch(this.info.api.toString() + "/v9/users/@me/channels", { method: "POST",
body: JSON.stringify({ "recipients": [this.author.id] }),
headers: this.headers
});
});
Message.contextmenu.addbutton("Edit", function () {
this.channel.editing = this;
document.getElementById("typebox").value = this.content;
}, null, _ => { return _.author.id === _.localuser.user.id; });
}
constructor(messagejson, owner) {
this.owner = owner;
this.headers = this.owner.headers;
for (const thing of Object.keys(messagejson)) {
this[thing] = messagejson[thing];
}
for (const thing in this.embeds) {
console.log(thing, this.embeds);
this.embeds[thing] = new Embed(this.embeds[thing], this);
}
this.author = new User(this.author, this.localuser);
for (const thing in this.mentions) {
this.mentions[thing] = new User(this.mentions[thing], this.localuser);
}
if (this.mentions.length || this.mention_roles.length) { //currently mention_roles isn't implemented on the spacebar servers
console.log(this.mentions, this.mention_roles);
}
if (this.mentionsuser(this.localuser.user)) {
console.log(this);
}
}
get channel() {
return this.owner;
}
get guild() {
return this.owner.guild;
}
get localuser() {
return this.owner.localuser;
}
get info() {
return this.owner.info;
}
messageevents(obj) {
Message.contextmenu.bind(obj, this);
obj.classList.add("messagediv");
}
mentionsuser(userd) {
if (userd instanceof User) {
return this.mentions.includes(userd);
}
else if (userd instanceof Member) {
return this.mentions.includes(userd.user);
}
}
getimages() {
const build = [];
for (const thing of this.attachments) {
if (thing.content_type.startsWith('image/')) {
build.push(thing);
}
}
return build;
}
async edit(content) {
return await fetch(this.info.api.toString() + "/channels/" + this.channel.id + "/messages/" + this.id, {
method: "PATCH",
headers: this.headers,
body: JSON.stringify({ content: content })
});
}
buildhtml(premessage) {
//premessage??=messages.lastChild;
const build = document.createElement('table');
const div = document.createElement("div");
if (this.message_reference) {
const replyline = document.createElement("div");
const line = document.createElement("hr");
const minipfp = document.createElement("img");
minipfp.classList.add("replypfp");
replyline.appendChild(line);
replyline.appendChild(minipfp);
const username = document.createElement("span");
replyline.appendChild(username);
const reply = document.createElement("div");
username.classList.add("username");
Member.resolve(this.author, this.guild).then(_ => {
username.style.color = _.getColor();
});
reply.classList.add("replytext");
replyline.appendChild(reply);
const line2 = document.createElement("hr");
replyline.appendChild(line2);
line2.classList.add("reply");
line.classList.add("startreply");
replyline.classList.add("replyflex");
fetch(this.info.api.toString() + "/v9/channels/" + this.message_reference.channel_id + "/messages?limit=1&around=" + this.message_reference.message_id, { headers: this.headers }).then(responce => responce.json()).then(responce => {
const author = new User(responce[0].author, this.localuser);
reply.appendChild(markdown(responce[0].content));
minipfp.src = author.getpfpsrc();
author.profileclick(minipfp);
username.textContent = author.username;
author.profileclick(username);
});
div.appendChild(replyline);
}
this.messageevents(div);
build.classList.add("message");
div.appendChild(build);
if ({ 0: true, 19: true }[this.type] || this.attachments.length !== 0) {
const pfpRow = document.createElement('th');
let pfpparent, current;
if (premessage != null) {
pfpparent = premessage.pfpparent;
pfpparent ??= premessage;
let pfpparent2 = pfpparent.all;
pfpparent2 ??= pfpparent;
const old = (new Date(pfpparent2.timestamp).getTime()) / 1000;
const newt = (new Date(this.timestamp).getTime()) / 1000;
current = (newt - old) > 600;
}
const combine = (premessage?.userid != this.author.id && premessage?.author?.id != this.author.id) || (current) || this.message_reference;
if (combine) {
const pfp = this.author.buildpfp();
this.author.profileclick(pfp);
pfpRow.appendChild(pfp);
}
else {
div["pfpparent"] = pfpparent;
}
pfpRow.classList.add("pfprow");
build.appendChild(pfpRow);
const text = document.createElement("th");
const texttxt = document.createElement("table");
texttxt.classList.add("commentrow");
text.appendChild(texttxt);
if (combine) {
const username = document.createElement("span");
username.classList.add("username");
this.author.profileclick(username);
Member.resolve(this.author, this.guild).then(_ => {
if (!_) {
return;
}
username.style.color = _.getColor();
});
username.textContent = this.author.username;
const userwrap = document.createElement("tr");
userwrap.appendChild(username);
if (this.author.bot) {
const username = document.createElement("span");
username.classList.add("bot");
username.textContent = "BOT";
userwrap.appendChild(username);
}
const time = document.createElement("span");
time.textContent = " " + formatTime(new Date(this.timestamp));
time.classList.add("timestamp");
userwrap.appendChild(time);
texttxt.appendChild(userwrap);
}
const messaged = markdown(this.content);
div["txt"] = messaged;
const messagedwrap = document.createElement("tr");
messagedwrap.appendChild(messaged);
texttxt.appendChild(messagedwrap);
build.appendChild(text);
if (this.attachments.length) {
console.log(this.attachments);
const attatch = document.createElement("tr");
for (const thing of this.attachments) {
const array = thing.url.split("/");
array.shift();
array.shift();
array.shift();
const src = this.info.cdn.toString() + array.join("/");
if (thing.content_type.startsWith('image/')) {
const img = document.createElement("img");
img.classList.add("messageimg");
img.onclick = function () {
const full = new Fullscreen(["img", img.src, ["fit"]]);
full.show();
};
img.src = src;
attatch.appendChild(img);
}
else {
attatch.appendChild(this.createunknown(thing.filename, thing.size, src));
}
}
messagedwrap.appendChild(attatch);
}
if (this.embeds.length) {
const embeds = document.createElement("tr");
for (const thing of this.embeds) {
embeds.appendChild(thing.generateHTML());
}
messagedwrap.appendChild(embeds);
}
//
}
else if (this.type === 7) {
const text = document.createElement("th");
const texttxt = document.createElement("table");
text.appendChild(texttxt);
build.appendChild(text);
const messaged = document.createElement("p");
div["txt"] = messaged;
messaged.textContent = "welcome: " + this.author.username;
const messagedwrap = document.createElement("tr");
messagedwrap.appendChild(messaged);
const time = document.createElement("span");
time.textContent = " " + formatTime(new Date(this.timestamp));
time.classList.add("timestamp");
messagedwrap.append(time);
texttxt.appendChild(messagedwrap);
}
div["userid"] = this.author.id;
div["all"] = this;
return (div);
}
createunknown(fname, fsize, src) {
const div = document.createElement("table");
div.classList.add("unknownfile");
const nametr = document.createElement("tr");
div.append(nametr);
const fileicon = document.createElement("td");
nametr.append(fileicon);
fileicon.append("🗎");
fileicon.classList.add("fileicon");
fileicon.rowSpan = 2;
const nametd = document.createElement("td");
if (src) {
const a = document.createElement("a");
a.href = src;
a.textContent = fname;
nametd.append(a);
}
else {
nametd.textContent = fname;
}
nametd.classList.add("filename");
nametr.append(nametd);
const sizetr = document.createElement("tr");
const size = document.createElement("td");
sizetr.append(size);
size.textContent = "Size:" + this.filesizehuman(fsize);
size.classList.add("filesize");
div.appendChild(sizetr);
return div;
}
filesizehuman(fsize) {
var i = fsize == 0 ? 0 : Math.floor(Math.log(fsize) / Math.log(1024));
return +((fsize / Math.pow(1024, i)).toFixed(2)) * 1 + ' ' + ['Bytes', 'Kilobytes', 'Megabytes', 'Gigabytes', 'Terabytes'][i];
}
}
function formatTime(date) {
const now = new Date();
const sameDay = date.getDate() === now.getDate() &&
date.getMonth() === now.getMonth() &&
date.getFullYear() === now.getFullYear();
const yesterday = new Date(now);
yesterday.setDate(now.getDate() - 1);
const isYesterday = date.getDate() === yesterday.getDate() &&
date.getMonth() === yesterday.getMonth() &&
date.getFullYear() === yesterday.getFullYear();
const formatTime = date => date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
if (sameDay) {
return `Today at ${formatTime(date)}`;
}
else if (isYesterday) {
return `Yesterday at ${formatTime(date)}`;
}
else {
return `${date.toLocaleDateString()} at ${formatTime(date)}`;
}
}
Message.setupcmenu();
export { Message };

246
.dist/permissions.js Normal file
View file

@ -0,0 +1,246 @@
export { Permissions };
class Permissions {
allow;
deny;
constructor(allow, deny = "") {
this.allow = BigInt(allow);
this.deny = BigInt(deny);
}
getPermisionbit(b, big) {
return Boolean((big >> BigInt(b)) & 1n);
}
setPermisionbit(b, state, big) {
const bit = 1n << BigInt(b);
return (big & ~bit) | (BigInt(state) << BigInt(b)); //thanks to geotale for this code :3
}
static map;
static info;
static makeMap() {
Permissions.info = [
{
name: "CREATE_INSTANT_INVITE",
readableName: "Create instance invite",
description: "Allows the user to create invites for the guild"
},
{
name: "KICK_MEMBERS",
readableName: "Kick members",
description: "Allows the user to kick members from the guild"
},
{
name: "BAN_MEMBERS",
readableName: "Ban members",
description: "Allows the user to ban members from the guild"
},
{
name: "ADMINISTRATOR",
readableName: "Administrator",
description: "Allows all permissions and bypasses channel permission overwrites"
},
{
name: "MANAGE_CHANNELS",
readableName: "Manage channels",
description: "Allows the user to manage and edit channels"
},
{
name: "MANAGE_GUILD",
readableName: "Manage guild",
description: "Allows management and editing of the guild"
},
{
name: "ADD_REACTIONS",
readableName: "Add reactions",
description: "Allows user to add reactions to messages"
},
{
name: "VIEW_AUDIT_LOG",
readableName: "View audit log",
description: "Allows the user to view the audit log"
},
{
name: "PRIORITY_SPEAKER",
readableName: "Priority speaker",
description: "Allows for using priority speaker in a voice channel"
},
{
name: "STREAM",
readableName: "Stream",
description: "Allows the user to stream"
},
{
name: "VIEW_CHANNEL",
readableName: "View channel",
description: "Allows the user to view the channel"
},
{
name: "SEND_MESSAGES",
readableName: "Send Messages",
description: "Allows user to send messages"
},
{
name: "SEND_TTS_MESSAGES",
readableName: "Send text-to-speech messages",
description: "Allows the user to send text-to-speech messages"
},
{
name: "MANAGE_MESSAGES",
readableName: "Manager messages",
description: "Allows the user to delete messages that aren't their own"
},
{
name: "EMBED_LINKS",
readableName: "Embed links",
description: "Allow links sent by this user to auto-embed"
},
{
name: "ATTACH_FILES",
readableName: "Attach files",
description: "Allows the user to attach files"
},
{
name: "READ_MESSAGE_HISTORY",
readableName: "Read message history",
description: "Allows user to read the message history"
},
{
name: "MENTION_EVERYONE",
readableName: "Mention everyone",
description: "Allows the user to mention everyone"
},
{
name: "USE_EXTERNAL_EMOJIS",
readableName: "Use external emojis",
description: "Allows the user to use external emojis"
},
{
name: "VIEW_GUILD_INSIGHTS",
readableName: "View guild insights",
description: "Allows the user to see guild insights"
},
{
name: "CONNECT",
readableName: "Connect",
description: "Allows the user to connect to a voice channel"
},
{
name: "SPEAK",
readableName: "Speak",
description: "Allows the user to speak in a voice channel"
},
{
name: "MUTE_MEMBERS",
readableName: "Mute members",
description: "Allows user to mute other members"
},
{
name: "DEAFEN_MEMBERS",
readableName: "Deafen members",
description: "Allows user to deafen other members"
},
{
name: "MOVE_MEMBERS",
readableName: "Move members",
description: "Allows the user to move members between voice channels"
},
{
name: "USE_VAD",
readableName: "use voice-activity-detection",
description: "Allows user to use voice-activity-detection"
},
{
name: "CHANGE_NICKNAME",
readableName: "Change nickname",
description: "Allows the user to change their own nickname"
},
{
name: "MANAGE_NICKNAMES",
readableName: "Manage nicknames",
description: "Allows user to change nicknames of other members"
},
{
name: "MANAGE_ROLES",
readableName: "Manage roles",
description: "Allows user to edit and manage roles"
},
{
name: "MANAGE_WEBHOOKS",
readableName: "Manage webhooks",
description: "Allows management and editing of webhooks"
},
{
name: "MANAGE_GUILD_EXPRESSIONS",
readableName: "Manage guild expressions",
description: "Allows for managing emoji, stickers, and soundboards"
},
{
name: "USE_APPLICATION_COMMANDS",
readableName: "Use application commands",
description: "Allows the user to use application commands"
},
{
name: "REQUEST_TO_SPEAK",
readableName: "Request to speak",
description: "Allows user to request to speak in stage channel"
},
{
name: "MANAGE_EVENTS",
readableName: "Manage events",
description: "Allows user to edit and manage events"
},
{
name: "MANAGE_THREADS",
readableName: "Manage threads",
description: "Allows the user to delete and archive threads and view all private threads"
},
{
name: "CREATE_PUBLIC_THREADS",
readableName: "Create public threads",
description: "Allows the user to create public threads"
},
{
name: "CREATE_PRIVATE_THREADS",
readableName: "Create private threads",
description: "Allows the user to create private threads"
},
{
name: "USE_EXTERNAL_STICKERS",
readableName: "Use external stickers",
description: "Allows user to use external stickers"
},
{
name: "SEND_MESSAGES_IN_THREADS",
readableName: "Send messages in threads",
description: "Allows the user to send messages in threads"
},
{
name: "USE_EMBEDDED_ACTIVITIES",
readableName: "Use embedded activities",
description: "Allows the user to use embedded activities"
},
{
name: "MODERATE_MEMBERS",
readableName: "Moderate members",
description: "Allows the user to time out other users to prevent them from sending or reacting to messages in chat and threads, and from speaking in voice and stage channels"
},
];
Permissions.map = {};
let i = 0;
for (const thing of Permissions.info) {
Permissions.map[i] = thing;
Permissions.map[thing.name] = i;
i++;
}
}
getPermision(name) {
if (this.getPermisionbit(Permissions.map[name], this.allow)) {
return 1;
}
else if (this.getPermisionbit(Permissions.map[name], this.deny)) {
return -1;
}
else {
return 0;
}
}
}
Permissions.makeMap();

28
.dist/role.js Normal file
View file

@ -0,0 +1,28 @@
export { Role };
import { Permissions } from "./permissions.js";
class Role {
permissions;
owner;
color;
id;
constructor(JSON, owner) {
for (const thing of Object.keys(JSON)) {
this[thing] = JSON[thing];
}
this.permissions = new Permissions(JSON.permissions);
this.owner = owner;
}
get guild() {
return this.owner;
}
get localuser() {
return this.guild.localuser;
}
getColor() {
if (this.color === 0) {
return null;
}
;
return `#${this.color.toString(16)}`;
}
}

93
.dist/service.js Normal file
View file

@ -0,0 +1,93 @@
function deleteoldcache() {
caches.delete("cache");
console.log("this ran :P");
}
async function putInCache(request, response) {
console.log(request, response);
const cache = await caches.open('cache');
console.log("Grabbed");
try {
console.log(await cache.put(request, response));
}
catch (error) {
console.error(error);
}
}
;
console.log("test");
let lastcache;
self.addEventListener("activate", async (event) => {
console.log("test2");
checkCache();
});
async function checkCache() {
if (checkedrecently) {
return;
}
const promise = await caches.match("/getupdates");
if (promise) {
lastcache = await promise.text();
}
console.log(lastcache);
fetch("/getupdates").then(async (data) => {
const text = await data.clone().text();
console.log(text, lastcache);
if (lastcache !== text) {
deleteoldcache();
putInCache("/getupdates", data.clone());
}
checkedrecently = true;
setTimeout(_ => { checkedrecently = false; }, 1000 * 60 * 30);
});
}
var checkedrecently = false;
function samedomain(url) {
return new URL(url).origin === self.origin;
}
function isindexhtml(url) {
console.log(url);
if (new URL(url).pathname.startsWith("/channels")) {
return true;
}
return false;
}
async function getfile(event) {
checkCache();
if (!samedomain(event.request.url)) {
return await fetch(event.request.clone());
}
const responseFromCache = await caches.match(event.request.url);
console.log(responseFromCache, caches);
if (responseFromCache) {
console.log("cache hit");
return responseFromCache;
}
if (isindexhtml(event.request.url)) {
console.log("is index.html");
const responseFromCache = await caches.match("/index.html");
if (responseFromCache) {
console.log("cache hit");
return responseFromCache;
}
const responseFromNetwork = await fetch("/index.html");
await putInCache("/index.html", responseFromNetwork.clone());
return responseFromNetwork;
}
const responseFromNetwork = await fetch(event.request.clone());
console.log(event.request.clone());
await putInCache(event.request.clone(), responseFromNetwork.clone());
try {
return responseFromNetwork;
}
catch (e) {
console.error(e);
}
}
self.addEventListener('fetch', (event) => {
try {
event.respondWith(getfile(event));
}
catch (e) {
console.error(e);
}
});

139
.dist/user.js Normal file
View file

@ -0,0 +1,139 @@
//const usercache={};
import { Member } from "./member.js";
import { markdown } from "./markdown.js";
import { Contextmenu } from "./contextmenu.js";
class User {
static userids = {};
owner;
hypotheticalpfp;
id;
avatar;
username;
bio;
discriminator;
pronouns;
bot;
static checkuser(userjson, owner) {
if (User.userids[userjson.id]) {
return User.userids[userjson.id];
}
else {
const tempuser = new User(userjson, owner, true);
User.userids[userjson.id] = tempuser;
return tempuser;
}
}
get info() {
return this.owner.info;
}
get localuser() {
return this.owner;
}
constructor(userjson, owner, dontclone = false) {
this.owner = owner;
if (!owner) {
console.error("missing localuser");
}
if (dontclone) {
for (const thing of Object.keys(userjson)) {
this[thing] = userjson[thing];
}
this.hypotheticalpfp = false;
}
else {
return User.checkuser(userjson, owner);
}
}
async resolvemember(guild) {
await Member.resolve(this, guild);
}
buildpfp() {
const pfp = document.createElement('img');
pfp.src = this.getpfpsrc();
pfp.classList.add("pfp");
pfp.classList.add("userid:" + this.id);
return pfp;
}
userupdate(json) {
if (json.avatar !== this.avatar) {
console.log;
this.changepfp(json.avatar);
}
}
changepfp(update) {
this.avatar = update;
this.hypotheticalpfp = false;
const src = this.getpfpsrc();
console.log(src);
for (const thing of document.getElementsByClassName("userid:" + this.id)) {
thing.src = src;
}
}
getpfpsrc() {
if (this.hypotheticalpfp) {
return this.avatar;
}
if (this.avatar != null) {
return this.info.cdn.toString() + "avatars/" + this.id + "/" + this.avatar + ".png";
}
else {
return this.info.cdn.toString() + "embed/avatars/3.png";
}
}
createjankpromises() {
new Promise(_ => { });
}
buildprofile(x, y) {
if (Contextmenu.currentmenu != "") {
Contextmenu.currentmenu.remove();
}
const div = document.createElement("table");
if (x !== -1) {
div.style.left = x + "px";
div.style.top = y + "px";
div.classList.add("profile");
}
else {
div.classList.add("hypoprofile");
}
{
const pfp = this.buildpfp();
const pfprow = document.createElement("tr");
div.appendChild(pfprow);
pfprow.appendChild(pfp);
}
{
const userbody = document.createElement("tr");
userbody.classList.add("infosection");
div.appendChild(userbody);
const usernamehtml = document.createElement("h2");
usernamehtml.textContent = this.username;
userbody.appendChild(usernamehtml);
const discrimatorhtml = document.createElement("h3");
discrimatorhtml.classList.add("tag");
discrimatorhtml.textContent = this.username + "#" + this.discriminator;
userbody.appendChild(discrimatorhtml);
const pronounshtml = document.createElement("p");
pronounshtml.textContent = this.pronouns;
pronounshtml.classList.add("pronouns");
userbody.appendChild(pronounshtml);
const rule = document.createElement("hr");
userbody.appendChild(rule);
const biohtml = markdown(this.bio);
userbody.appendChild(biohtml);
}
console.log(div);
if (x !== -1) {
Contextmenu.currentmenu = div;
document.body.appendChild(div);
}
return div;
}
profileclick(obj) {
obj.onclick = e => {
this.buildprofile(e.clientX, e.clientY);
e.stopPropagation();
};
}
}
export { User };