Merge remote-tracking branch 'upstream/main'
This commit is contained in:
commit
9005d2554f
28 changed files with 2304 additions and 1254 deletions
146
.dist/channel.js
146
.dist/channel.js
|
@ -3,11 +3,10 @@ import { Message } from "./message.js";
|
||||||
import { Voice } from "./audio.js";
|
import { Voice } from "./audio.js";
|
||||||
import { Contextmenu } from "./contextmenu.js";
|
import { Contextmenu } from "./contextmenu.js";
|
||||||
import { Fullscreen } from "./fullscreen.js";
|
import { Fullscreen } from "./fullscreen.js";
|
||||||
import { markdown } from "./markdown.js";
|
|
||||||
import { Permissions } from "./permissions.js";
|
import { Permissions } from "./permissions.js";
|
||||||
import { Settings, RoleList } from "./settings.js";
|
import { Settings, RoleList } from "./settings.js";
|
||||||
import { InfiniteScroller } from "./infiniteScroller.js";
|
import { InfiniteScroller } from "./infiniteScroller.js";
|
||||||
Settings;
|
import { SnowFlake } from "./snowflake.js";
|
||||||
class Channel {
|
class Channel {
|
||||||
editing;
|
editing;
|
||||||
type;
|
type;
|
||||||
|
@ -36,8 +35,8 @@ class Channel {
|
||||||
static contextmenu = new Contextmenu("channel menu");
|
static contextmenu = new Contextmenu("channel menu");
|
||||||
replyingto;
|
replyingto;
|
||||||
infinite;
|
infinite;
|
||||||
idToPrev = {};
|
idToPrev = new Map();
|
||||||
idToNext = {};
|
idToNext = new Map();
|
||||||
static setupcontextmenu() {
|
static setupcontextmenu() {
|
||||||
this.contextmenu.addbutton("Copy channel id", function () {
|
this.contextmenu.addbutton("Copy channel id", function () {
|
||||||
console.log(this);
|
console.log(this);
|
||||||
|
@ -74,22 +73,24 @@ class Channel {
|
||||||
setUpInfiniteScroller() {
|
setUpInfiniteScroller() {
|
||||||
const ids = {};
|
const ids = {};
|
||||||
this.infinite = new InfiniteScroller(async function (id, offset) {
|
this.infinite = new InfiniteScroller(async function (id, offset) {
|
||||||
|
const snowflake = SnowFlake.getSnowFlakeFromID(id, Message);
|
||||||
if (offset === 1) {
|
if (offset === 1) {
|
||||||
if (this.idToPrev[id]) {
|
if (this.idToPrev.get(snowflake)) {
|
||||||
return this.idToPrev[id];
|
return this.idToPrev.get(snowflake)?.id;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
await this.grabmoremessages(id);
|
await this.grabBefore(id);
|
||||||
return this.idToPrev[id];
|
return this.idToPrev.get(snowflake)?.id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return this.idToNext[id];
|
return this.idToNext.get(snowflake)?.id;
|
||||||
}
|
}
|
||||||
}.bind(this), function (id) {
|
}.bind(this), function (id) {
|
||||||
let res;
|
let res;
|
||||||
const promise = new Promise(_ => { res = _; });
|
const promise = new Promise(_ => { res = _; });
|
||||||
const html = this.messageids[id].buildhtml(this.messageids[this.idToPrev[id]], promise);
|
const snowflake = SnowFlake.getSnowFlakeFromID(id, Message);
|
||||||
|
const html = this.messageids.get(snowflake).buildhtml(this.messageids.get(this.idToPrev.get(snowflake)), promise);
|
||||||
ids[id] = res;
|
ids[id] = res;
|
||||||
return html;
|
return html;
|
||||||
}.bind(this), async function (id) {
|
}.bind(this), async function (id) {
|
||||||
|
@ -107,28 +108,27 @@ class Channel {
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
this.headers = this.owner.headers;
|
this.headers = this.owner.headers;
|
||||||
this.name = JSON.name;
|
this.name = JSON.name;
|
||||||
this.id = JSON.id;
|
this.id = new SnowFlake(JSON.id, this);
|
||||||
this.parent_id = JSON.parent_id;
|
this.parent_id = new SnowFlake(JSON.parent_id, undefined);
|
||||||
this.parent = null;
|
this.parent = null;
|
||||||
this.children = [];
|
this.children = [];
|
||||||
this.guild_id = JSON.guild_id;
|
this.guild_id = JSON.guild_id;
|
||||||
this.messageids = {};
|
this.messageids = new Map();
|
||||||
this.permission_overwrites = {};
|
this.permission_overwrites = new Map();
|
||||||
this.permission_overwritesar = [];
|
this.permission_overwritesar = [];
|
||||||
for (const thing of JSON.permission_overwrites) {
|
for (const thing of JSON.permission_overwrites) {
|
||||||
console.log(thing);
|
|
||||||
if (thing.id === "1182819038095799904" || thing.id === "1182820803700625444") {
|
if (thing.id === "1182819038095799904" || thing.id === "1182820803700625444") {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
this.permission_overwrites[thing.id] = new Permissions(thing.allow, thing.deny);
|
this.permission_overwrites.set(thing.id, new Permissions(thing.allow, thing.deny));
|
||||||
this.permission_overwritesar.push([thing.id, this.permission_overwrites[thing.id]]);
|
this.permission_overwritesar.push([thing.id, this.permission_overwrites.get(thing.id)]);
|
||||||
}
|
}
|
||||||
this.topic = JSON.topic;
|
this.topic = JSON.topic;
|
||||||
this.nsfw = JSON.nsfw;
|
this.nsfw = JSON.nsfw;
|
||||||
this.position = JSON.position;
|
this.position = JSON.position;
|
||||||
this.lastreadmessageid = null;
|
this.lastreadmessageid = null;
|
||||||
this.lastmessageid = JSON.last_message_id;
|
this.lastmessageid = SnowFlake.getSnowFlakeFromID(JSON.last_message_id, Message);
|
||||||
this.setUpInfiniteScroller();
|
this.setUpInfiniteScroller();
|
||||||
}
|
}
|
||||||
isAdmin() {
|
isAdmin() {
|
||||||
|
@ -144,7 +144,7 @@ class Channel {
|
||||||
return this.owner.info;
|
return this.owner.info;
|
||||||
}
|
}
|
||||||
readStateInfo(json) {
|
readStateInfo(json) {
|
||||||
this.lastreadmessageid = json.last_message_id;
|
this.lastreadmessageid = SnowFlake.getSnowFlakeFromID(json.last_message_id, Message);
|
||||||
this.mentions = json.mention_count;
|
this.mentions = json.mention_count;
|
||||||
this.mentions ??= 0;
|
this.mentions ??= 0;
|
||||||
this.lastpin = json.last_pin_timestamp;
|
this.lastpin = json.last_pin_timestamp;
|
||||||
|
@ -153,15 +153,15 @@ class Channel {
|
||||||
if (!this.hasPermission("VIEW_CHANNEL")) {
|
if (!this.hasPermission("VIEW_CHANNEL")) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return this.lastmessageid !== this.lastreadmessageid && this.type !== 4;
|
return this.lastmessageid !== this.lastreadmessageid && this.type !== 4 && !!this.lastmessageid.id;
|
||||||
}
|
}
|
||||||
hasPermission(name, member = this.guild.member) {
|
hasPermission(name, member = this.guild.member) {
|
||||||
if (member.isAdmin()) {
|
if (member.isAdmin()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
for (const thing of member.roles) {
|
for (const thing of member.roles) {
|
||||||
if (this.permission_overwrites[thing.id]) {
|
if (this.permission_overwrites.get(thing.id.id)) {
|
||||||
let perm = this.permission_overwrites[thing.id].getPermission(name);
|
let perm = this.permission_overwrites.get(thing.id.id).getPermission(name);
|
||||||
if (perm) {
|
if (perm) {
|
||||||
return perm === 1;
|
return perm === 1;
|
||||||
}
|
}
|
||||||
|
@ -182,7 +182,7 @@ class Channel {
|
||||||
this.children.sort((a, b) => { return a.position - b.position; });
|
this.children.sort((a, b) => { return a.position - b.position; });
|
||||||
}
|
}
|
||||||
resolveparent(guild) {
|
resolveparent(guild) {
|
||||||
this.parent = guild.channelids[this.parent_id];
|
this.parent = guild.channelids[this.parent_id?.id];
|
||||||
this.parent ??= null;
|
this.parent ??= null;
|
||||||
if (this.parent !== null) {
|
if (this.parent !== null) {
|
||||||
this.parent.children.push(this);
|
this.parent.children.push(this);
|
||||||
|
@ -344,7 +344,7 @@ class Channel {
|
||||||
if (!this.hasunreads) {
|
if (!this.hasunreads) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fetch(this.info.api.toString() + "/v9/channels/" + this.id + "/messages/" + this.lastmessageid + "/ack", {
|
fetch(this.info.api.toString() + "/channels/" + this.id + "/messages/" + this.lastmessageid + "/ack", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: this.headers,
|
headers: this.headers,
|
||||||
body: JSON.stringify({})
|
body: JSON.stringify({})
|
||||||
|
@ -434,8 +434,8 @@ class Channel {
|
||||||
["textbox", "Channel name:", this.name, function () { name = this.value; }],
|
["textbox", "Channel name:", this.name, function () { name = this.value; }],
|
||||||
["mdbox", "Channel topic:", this.topic, function () { topic = this.value; }],
|
["mdbox", "Channel topic:", this.topic, function () { topic = this.value; }],
|
||||||
["checkbox", "NSFW Channel", this.nsfw, function () { nsfw = this.checked; }],
|
["checkbox", "NSFW Channel", this.nsfw, function () { nsfw = this.checked; }],
|
||||||
["button", "", "submit", function () {
|
["button", "", "submit", () => {
|
||||||
fetch(this.info.api.toString() + "/v9/channels/" + thisid, {
|
fetch(this.info.api.toString() + "/channels/" + thisid, {
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
headers: this.headers,
|
headers: this.headers,
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
|
@ -458,7 +458,7 @@ class Channel {
|
||||||
console.log(full);
|
console.log(full);
|
||||||
}
|
}
|
||||||
deleteChannel() {
|
deleteChannel() {
|
||||||
fetch(this.info.api.toString() + "/v9/channels/" + this.id, {
|
fetch(this.info.api.toString() + "/channels/" + this.id, {
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
headers: this.headers
|
headers: this.headers
|
||||||
});
|
});
|
||||||
|
@ -496,11 +496,12 @@ class Channel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async getmessage(id) {
|
async getmessage(id) {
|
||||||
if (this.messageids[id]) {
|
const snowflake = SnowFlake.getSnowFlakeFromID(id, Message);
|
||||||
return this.messageids[id];
|
if (snowflake.getObject()) {
|
||||||
|
return snowflake.getObject();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const gety = await fetch(this.info.api.toString() + "/v9/channels/" + this.id + "/messages?limit=1&around=" + id, { headers: this.headers });
|
const gety = await fetch(this.info.api.toString() + "/channels/" + this.id + "/messages?limit=1&around=" + id, { headers: this.headers });
|
||||||
const json = await gety.json();
|
const json = await gety.json();
|
||||||
return new Message(json[0], this);
|
return new Message(json[0], this);
|
||||||
}
|
}
|
||||||
|
@ -528,8 +529,9 @@ class Channel {
|
||||||
history.pushState(null, null, "/channels/" + this.guild_id + "/" + this.id);
|
history.pushState(null, null, "/channels/" + this.guild_id + "/" + this.id);
|
||||||
document.getElementById("channelname").textContent = "#" + this.name;
|
document.getElementById("channelname").textContent = "#" + this.name;
|
||||||
console.log(this);
|
console.log(this);
|
||||||
document.getElementById("typebox").disabled = !this.canMessage;
|
document.getElementById("typebox").contentEditable = "" + this.canMessage;
|
||||||
}
|
}
|
||||||
|
lastmessage;
|
||||||
async putmessages() {
|
async putmessages() {
|
||||||
if (this.allthewayup) {
|
if (this.allthewayup) {
|
||||||
return;
|
return;
|
||||||
|
@ -546,12 +548,15 @@ class Channel {
|
||||||
for (const thing of response) {
|
for (const thing of response) {
|
||||||
const message = new Message(thing, this);
|
const message = new Message(thing, this);
|
||||||
if (prev) {
|
if (prev) {
|
||||||
this.idToNext[message.id] = prev.id;
|
this.idToNext.set(message.id, prev.id);
|
||||||
this.idToPrev[prev.id] = message.id;
|
this.idToPrev.set(prev.id, message.id);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.lastmessage = message;
|
||||||
}
|
}
|
||||||
prev = message;
|
prev = message;
|
||||||
if (this.messageids[message.id] === undefined) {
|
if (this.messageids.get(message.id) === undefined) {
|
||||||
this.messageids[message.id] = message;
|
this.messageids.set(message.id, message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -564,7 +569,7 @@ class Channel {
|
||||||
}
|
}
|
||||||
this.children = build;
|
this.children = build;
|
||||||
}
|
}
|
||||||
async grabmoremessages(id) {
|
async grabBefore(id) {
|
||||||
if (this.allthewayup) {
|
if (this.allthewayup) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -575,7 +580,7 @@ class Channel {
|
||||||
if (response.length === 0) {
|
if (response.length === 0) {
|
||||||
this.allthewayup = true;
|
this.allthewayup = true;
|
||||||
}
|
}
|
||||||
let previd = id;
|
let previd = SnowFlake.getSnowFlakeFromID(id, Message);
|
||||||
for (const i in response) {
|
for (const i in response) {
|
||||||
let messager;
|
let messager;
|
||||||
if (!next) {
|
if (!next) {
|
||||||
|
@ -591,11 +596,11 @@ class Channel {
|
||||||
next = undefined;
|
next = undefined;
|
||||||
console.log("ohno", +i + 1);
|
console.log("ohno", +i + 1);
|
||||||
}
|
}
|
||||||
if (this.messageids[messager.id] === undefined) {
|
if (this.messageids.get(messager.id) === undefined) {
|
||||||
this.idToNext[messager.id] = previd;
|
this.idToNext.set(messager.id, previd);
|
||||||
this.idToPrev[previd] = messager.id;
|
this.idToPrev.set(previd, messager.id);
|
||||||
previd = messager.id;
|
previd = messager.id;
|
||||||
this.messageids[messager.id] = messager;
|
this.messageids.set(messager.id, messager);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.log("How???");
|
console.log("How???");
|
||||||
|
@ -612,17 +617,47 @@ class Channel {
|
||||||
buildmessages() {
|
buildmessages() {
|
||||||
const messages = document.getElementById("channelw");
|
const messages = document.getElementById("channelw");
|
||||||
messages.innerHTML = "";
|
messages.innerHTML = "";
|
||||||
messages.append(this.infinite.getDiv(this.lastmessageid));
|
let id;
|
||||||
|
if (this.messageids.get(this.lastreadmessageid)) {
|
||||||
|
id = this.lastreadmessageid;
|
||||||
|
}
|
||||||
|
else if (this.lastmessage.id) {
|
||||||
|
id = this.goBackIds(this.lastmessage.id, 50);
|
||||||
|
console.log("shouldn't");
|
||||||
|
}
|
||||||
|
messages.append(this.infinite.getDiv(id.id));
|
||||||
|
}
|
||||||
|
goBackIds(id, back) {
|
||||||
|
while (back !== 0) {
|
||||||
|
const nextid = this.idToPrev.get(id);
|
||||||
|
if (nextid) {
|
||||||
|
id = nextid;
|
||||||
|
console.log(id);
|
||||||
|
back--;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return id;
|
||||||
}
|
}
|
||||||
updateChannel(JSON) {
|
updateChannel(JSON) {
|
||||||
this.type = JSON.type;
|
this.type = JSON.type;
|
||||||
this.name = JSON.name;
|
this.name = JSON.name;
|
||||||
this.parent_id = JSON.parent_id;
|
this.parent_id = new SnowFlake(JSON.parent_id, undefined);
|
||||||
this.parent = null;
|
this.parent = null;
|
||||||
this.children = [];
|
this.children = [];
|
||||||
this.guild_id = JSON.guild_id;
|
this.guild_id = JSON.guild_id;
|
||||||
this.messageids = {};
|
this.messageids = new Map();
|
||||||
this.permission_overwrites = JSON.permission_overwrites;
|
this.permission_overwrites = new Map();
|
||||||
|
for (const thing of JSON.permission_overwrites) {
|
||||||
|
if (thing.id === "1182819038095799904" || thing.id === "1182820803700625444") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
this.permission_overwrites.set(thing.id, new Permissions(thing.allow, thing.deny));
|
||||||
|
this.permission_overwritesar.push([thing.id, this.permission_overwrites.get(thing.id)]);
|
||||||
|
}
|
||||||
this.topic = JSON.topic;
|
this.topic = JSON.topic;
|
||||||
this.nsfw = JSON.nsfw;
|
this.nsfw = JSON.nsfw;
|
||||||
}
|
}
|
||||||
|
@ -658,9 +693,9 @@ class Channel {
|
||||||
if (replyingto) {
|
if (replyingto) {
|
||||||
replyjson =
|
replyjson =
|
||||||
{
|
{
|
||||||
"guild_id": replyingto.guild.id,
|
"guild_id": replyingto.guild.id.id,
|
||||||
"channel_id": replyingto.channel.id,
|
"channel_id": replyingto.channel.id.id,
|
||||||
"message_id": replyingto.id,
|
"message_id": replyingto.id.id,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
@ -707,10 +742,11 @@ class Channel {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const messagez = new Message(messagep.d, this);
|
const messagez = new Message(messagep.d, this);
|
||||||
this.idToNext[this.lastmessageid] = messagez.id;
|
console.log(this.lastmessageid, messagez.id, ":3");
|
||||||
this.idToPrev[messagez.id] = this.lastmessageid;
|
this.idToNext.set(this.lastmessageid, messagez.id);
|
||||||
|
this.idToPrev.set(messagez.id, this.lastmessageid);
|
||||||
this.lastmessageid = messagez.id;
|
this.lastmessageid = messagez.id;
|
||||||
this.messageids[messagez.id] = messagez;
|
this.messageids.set(messagez.id, messagez);
|
||||||
if (messagez.author === this.localuser.user) {
|
if (messagez.author === this.localuser.user) {
|
||||||
this.lastreadmessageid = messagez.id;
|
this.lastreadmessageid = messagez.id;
|
||||||
if (this.myhtml) {
|
if (this.myhtml) {
|
||||||
|
@ -745,10 +781,10 @@ class Channel {
|
||||||
if (!("Notification" in window)) {
|
if (!("Notification" in window)) {
|
||||||
}
|
}
|
||||||
else if (Notification.permission === "granted") {
|
else if (Notification.permission === "granted") {
|
||||||
let noticontent = markdown(message.content).textContent;
|
let noticontent = message.content.textContent;
|
||||||
if (message.embeds[0]) {
|
if (message.embeds[0]) {
|
||||||
noticontent ||= message.embeds[0].json.title;
|
noticontent ||= message.embeds[0].json.title;
|
||||||
noticontent ||= markdown(message.embeds[0].json.description).textContent;
|
noticontent ||= message.content.textContent;
|
||||||
}
|
}
|
||||||
noticontent ||= "Blank Message";
|
noticontent ||= "Blank Message";
|
||||||
let imgurl = null;
|
let imgurl = null;
|
||||||
|
@ -790,11 +826,11 @@ class Channel {
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
const perm = new Permissions("0", "0");
|
const perm = new Permissions("0", "0");
|
||||||
this.permission_overwrites[role.id] = perm;
|
this.permission_overwrites.set(role.id.id, perm);
|
||||||
this.permission_overwritesar.push([role.id, perm]);
|
this.permission_overwritesar.push([role.id, perm]);
|
||||||
}
|
}
|
||||||
async updateRolePermissions(id, perms) {
|
async updateRolePermissions(id, perms) {
|
||||||
const permission = this.permission_overwrites[id];
|
const permission = this.permission_overwrites.get(id);
|
||||||
permission.allow = perms.allow;
|
permission.allow = perms.allow;
|
||||||
permission.deny = perms.deny;
|
permission.deny = perms.deny;
|
||||||
await fetch(this.info.api.toString() + "/channels/" + this.id + "/permissions/" + id, {
|
await fetch(this.info.api.toString() + "/channels/" + this.id + "/permissions/" + id, {
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { Guild } from "./guild.js";
|
||||||
import { Channel } from "./channel.js";
|
import { Channel } from "./channel.js";
|
||||||
import { Message } from "./message.js";
|
import { Message } from "./message.js";
|
||||||
import { User } from "./user.js";
|
import { User } from "./user.js";
|
||||||
|
import { SnowFlake } from "./snowflake.js";
|
||||||
class Direct extends Guild {
|
class Direct extends Guild {
|
||||||
constructor(JSON, owner) {
|
constructor(JSON, owner) {
|
||||||
super(-1, owner, null);
|
super(-1, owner, null);
|
||||||
|
@ -14,16 +15,16 @@ class Direct extends Guild {
|
||||||
this.headers = this.localuser.headers;
|
this.headers = this.localuser.headers;
|
||||||
this.channels = [];
|
this.channels = [];
|
||||||
this.channelids = {};
|
this.channelids = {};
|
||||||
this.id = "@me";
|
this.id = new SnowFlake("@me", this);
|
||||||
this.properties = {};
|
this.properties = {};
|
||||||
this.roles = [];
|
this.roles = [];
|
||||||
this.roleids = {};
|
this.roleids = new Map();
|
||||||
this.prevchannel = undefined;
|
this.prevchannel = undefined;
|
||||||
this.properties.name = "Direct Messages";
|
this.properties.name = "Direct Messages";
|
||||||
for (const thing of JSON) {
|
for (const thing of JSON) {
|
||||||
const temp = new Group(thing, this);
|
const temp = new Group(thing, this);
|
||||||
this.channels.push(temp);
|
this.channels.push(temp);
|
||||||
this.channelids[temp.id] = temp;
|
this.channelids[temp.id.id] = temp;
|
||||||
}
|
}
|
||||||
this.headchannels = this.channels;
|
this.headchannels = this.channels;
|
||||||
}
|
}
|
||||||
|
@ -36,7 +37,7 @@ class Direct extends Guild {
|
||||||
}
|
}
|
||||||
sortchannels() {
|
sortchannels() {
|
||||||
this.headchannels.sort((a, b) => {
|
this.headchannels.sort((a, b) => {
|
||||||
const result = (BigInt(a.lastmessageid) - BigInt(b.lastmessageid));
|
const result = (a.lastmessageid.getUnixTime() - b.lastmessageid.getUnixTime());
|
||||||
return Number(-result);
|
return Number(-result);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -72,15 +73,15 @@ class Group extends Channel {
|
||||||
this.user = this.localuser.user;
|
this.user = this.localuser.user;
|
||||||
}
|
}
|
||||||
this.name ??= this.localuser.user.username;
|
this.name ??= this.localuser.user.username;
|
||||||
this.id = JSON.id;
|
this.id = new SnowFlake(JSON.id, this);
|
||||||
this.parent_id = null;
|
this.parent_id = null;
|
||||||
this.parent = null;
|
this.parent = null;
|
||||||
this.children = [];
|
this.children = [];
|
||||||
this.guild_id = "@me";
|
this.guild_id = "@me";
|
||||||
this.messageids = {};
|
this.messageids = new Map();
|
||||||
this.permission_overwrites = {};
|
this.permission_overwrites = new Map();
|
||||||
this.lastmessageid = JSON.last_message_id;
|
this.lastmessageid = SnowFlake.getSnowFlakeFromID(JSON.last_message_id, Message);
|
||||||
this.lastmessageid ??= "0";
|
this.lastmessageid ??= new SnowFlake("0", undefined);
|
||||||
this.mentions = 0;
|
this.mentions = 0;
|
||||||
this.setUpInfiniteScroller();
|
this.setUpInfiniteScroller();
|
||||||
}
|
}
|
||||||
|
@ -116,10 +117,10 @@ class Group extends Channel {
|
||||||
}
|
}
|
||||||
messageCreate(messagep) {
|
messageCreate(messagep) {
|
||||||
const messagez = new Message(messagep.d, this);
|
const messagez = new Message(messagep.d, this);
|
||||||
this.idToNext[this.lastmessageid] = messagez.id;
|
this.idToNext.set(this.lastmessageid, messagez.id);
|
||||||
this.idToPrev[messagez.id] = this.lastmessageid;
|
this.idToPrev.set(messagez.id, this.lastmessageid);
|
||||||
this.lastmessageid = messagez.id;
|
this.lastmessageid = messagez.id;
|
||||||
this.messageids[messagez.id] = messagez;
|
this.messageids.set(messagez.id, messagez);
|
||||||
if (messagez.author === this.localuser.user) {
|
if (messagez.author === this.localuser.user) {
|
||||||
this.lastreadmessageid = messagez.id;
|
this.lastreadmessageid = messagez.id;
|
||||||
if (this.myhtml) {
|
if (this.myhtml) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Fullscreen } from "./fullscreen.js";
|
import { Fullscreen } from "./fullscreen.js";
|
||||||
import { markdown } from "./markdown.js";
|
import { MarkDown } from "./markdown.js";
|
||||||
class Embed {
|
class Embed {
|
||||||
type;
|
type;
|
||||||
owner;
|
owner;
|
||||||
|
@ -27,6 +27,18 @@ class Embed {
|
||||||
return document.createElement("div"); //prevent errors by giving blank div
|
return document.createElement("div"); //prevent errors by giving blank div
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
get message() {
|
||||||
|
return this.owner;
|
||||||
|
}
|
||||||
|
get channel() {
|
||||||
|
return this.message.channel;
|
||||||
|
}
|
||||||
|
get guild() {
|
||||||
|
return this.channel.guild;
|
||||||
|
}
|
||||||
|
get localuser() {
|
||||||
|
return this.guild.localuser;
|
||||||
|
}
|
||||||
generateRich() {
|
generateRich() {
|
||||||
console.log(this.json);
|
console.log(this.json);
|
||||||
const div = document.createElement("div");
|
const div = document.createElement("div");
|
||||||
|
@ -55,7 +67,7 @@ class Embed {
|
||||||
embed.append(authorline);
|
embed.append(authorline);
|
||||||
}
|
}
|
||||||
const title = document.createElement("a");
|
const title = document.createElement("a");
|
||||||
title.append(markdown(this.json.title));
|
title.append(new MarkDown(this.json.title, this.channel).makeHTML());
|
||||||
if (this.json.url) {
|
if (this.json.url) {
|
||||||
title.href = this.json.url;
|
title.href = this.json.url;
|
||||||
}
|
}
|
||||||
|
@ -63,7 +75,7 @@ class Embed {
|
||||||
embed.append(title);
|
embed.append(title);
|
||||||
if (this.json.description) {
|
if (this.json.description) {
|
||||||
const p = document.createElement("p");
|
const p = document.createElement("p");
|
||||||
p.append(markdown(this.json.description));
|
p.append(new MarkDown(this.json.description, this.channel).makeHTML());
|
||||||
embed.append(p);
|
embed.append(p);
|
||||||
}
|
}
|
||||||
embed.append(document.createElement("br"));
|
embed.append(document.createElement("br"));
|
||||||
|
@ -74,7 +86,7 @@ class Embed {
|
||||||
b.textContent = thing.name;
|
b.textContent = thing.name;
|
||||||
div.append(b);
|
div.append(b);
|
||||||
const p = document.createElement("p");
|
const p = document.createElement("p");
|
||||||
p.append(markdown(thing.value));
|
p.append(new MarkDown(thing.value, this.channel).makeHTML());
|
||||||
p.classList.add("embedp");
|
p.classList.add("embedp");
|
||||||
div.append(p);
|
div.append(p);
|
||||||
if (thing.inline) {
|
if (thing.inline) {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { Role } from "./role.js";
|
||||||
import { Fullscreen } from "./fullscreen.js";
|
import { Fullscreen } from "./fullscreen.js";
|
||||||
import { Member } from "./member.js";
|
import { Member } from "./member.js";
|
||||||
import { Settings, RoleList } from "./settings.js";
|
import { Settings, RoleList } from "./settings.js";
|
||||||
|
import { SnowFlake } from "./snowflake.js";
|
||||||
class Guild {
|
class Guild {
|
||||||
owner;
|
owner;
|
||||||
headers;
|
headers;
|
||||||
|
@ -67,30 +68,30 @@ class Guild {
|
||||||
s1.options.push(new RoleList(permlist, this, this.updateRolePermissions.bind(this)));
|
s1.options.push(new RoleList(permlist, this, this.updateRolePermissions.bind(this)));
|
||||||
settings.show();
|
settings.show();
|
||||||
}
|
}
|
||||||
constructor(JSON, owner, member) {
|
constructor(json, owner, member) {
|
||||||
if (JSON === -1) {
|
if (json === -1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
this.headers = this.owner.headers;
|
this.headers = this.owner.headers;
|
||||||
this.channels = [];
|
this.channels = [];
|
||||||
this.channelids = {};
|
this.channelids = {};
|
||||||
this.id = JSON.id;
|
this.id = new SnowFlake(json.id, this);
|
||||||
this.properties = JSON.properties;
|
this.properties = json.properties;
|
||||||
this.roles = [];
|
this.roles = [];
|
||||||
this.roleids = {};
|
this.roleids = new Map();
|
||||||
this.prevchannel = undefined;
|
this.prevchannel = undefined;
|
||||||
this.message_notifications = 0;
|
this.message_notifications = 0;
|
||||||
for (const roley of JSON.roles) {
|
for (const roley of json.roles) {
|
||||||
const roleh = new Role(roley, this);
|
const roleh = new Role(roley, this);
|
||||||
this.roles.push(roleh);
|
this.roles.push(roleh);
|
||||||
this.roleids[roleh.id] = roleh;
|
this.roleids.set(roleh.id, roleh);
|
||||||
}
|
}
|
||||||
Member.resolve(member, this).then(_ => this.member = _);
|
Member.resolve(member, this).then(_ => this.member = _);
|
||||||
for (const thing of JSON.channels) {
|
for (const thing of json.channels) {
|
||||||
const temp = new Channel(thing, this);
|
const temp = new Channel(thing, this);
|
||||||
this.channels.push(temp);
|
this.channels.push(temp);
|
||||||
this.channelids[temp.id] = temp;
|
this.channelids[temp.id.id] = temp;
|
||||||
}
|
}
|
||||||
this.headchannels = [];
|
this.headchannels = [];
|
||||||
for (const thing of this.channels) {
|
for (const thing of this.channels) {
|
||||||
|
@ -118,7 +119,7 @@ class Guild {
|
||||||
headers: this.headers,
|
headers: this.headers,
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
"guilds": {
|
"guilds": {
|
||||||
[this.id]: {
|
[this.id.id]: {
|
||||||
"message_notifications": noti
|
"message_notifications": noti
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -237,7 +238,7 @@ class Guild {
|
||||||
const noti = document.createElement("div");
|
const noti = document.createElement("div");
|
||||||
noti.classList.add("unread");
|
noti.classList.add("unread");
|
||||||
divy.append(noti);
|
divy.append(noti);
|
||||||
this.localuser.guildhtml[this.id] = divy;
|
this.localuser.guildhtml[this.id.id] = divy;
|
||||||
if (this.properties.icon != null) {
|
if (this.properties.icon != null) {
|
||||||
const img = document.createElement("img");
|
const img = document.createElement("img");
|
||||||
img.classList.add("pfp", "servericon");
|
img.classList.add("pfp", "servericon");
|
||||||
|
@ -366,16 +367,10 @@ class Guild {
|
||||||
body: JSON.stringify(build)
|
body: JSON.stringify(build)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
getRole(ID) {
|
|
||||||
if (!this.roleids[ID]) {
|
|
||||||
console.error(`role id ${ID} does not exist`, this.roleids);
|
|
||||||
}
|
|
||||||
return this.roleids[ID];
|
|
||||||
}
|
|
||||||
hasRole(r) {
|
hasRole(r) {
|
||||||
console.log("this should run");
|
console.log("this should run");
|
||||||
if ((typeof r) !== (typeof "")) {
|
if (r instanceof Role) {
|
||||||
r = r.id;
|
r = r.id.id;
|
||||||
}
|
}
|
||||||
return this.member.hasRole(r);
|
return this.member.hasRole(r);
|
||||||
}
|
}
|
||||||
|
@ -397,10 +392,10 @@ class Guild {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
loadGuild() {
|
loadGuild() {
|
||||||
this.localuser.loadGuild(this.id);
|
this.localuser.loadGuild(this.id.id);
|
||||||
}
|
}
|
||||||
updateChannel(JSON) {
|
updateChannel(JSON) {
|
||||||
this.channelids[JSON.id].updateChannel(JSON);
|
SnowFlake.getSnowFlakeFromID(JSON.id, Channel).getObject().updateChannel(JSON);
|
||||||
this.headchannels = [];
|
this.headchannels = [];
|
||||||
for (const thing of this.channels) {
|
for (const thing of this.channels) {
|
||||||
thing.children = [];
|
thing.children = [];
|
||||||
|
@ -507,7 +502,7 @@ class Guild {
|
||||||
});
|
});
|
||||||
const json = await fetched.json();
|
const json = await fetched.json();
|
||||||
const role = new Role(json, this);
|
const role = new Role(json, this);
|
||||||
this.roleids[role.id] = role;
|
this.roleids[role.id.id] = role;
|
||||||
this.roles.push(role);
|
this.roles.push(role);
|
||||||
return role;
|
return role;
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,7 +109,7 @@ async function enter(event) {
|
||||||
if (event.key === "Enter" && !event.shiftKey) {
|
if (event.key === "Enter" && !event.shiftKey) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (channel.editing) {
|
if (channel.editing) {
|
||||||
channel.editing.edit((typebox).value);
|
channel.editing.edit(markdown.rawString);
|
||||||
channel.editing = null;
|
channel.editing = null;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -119,7 +119,7 @@ async function enter(event) {
|
||||||
replyingto.div.classList.remove("replying");
|
replyingto.div.classList.remove("replying");
|
||||||
}
|
}
|
||||||
thisuser.channelfocus.replyingto = null;
|
thisuser.channelfocus.replyingto = null;
|
||||||
channel.sendMessage(typebox.value, {
|
channel.sendMessage(markdown.rawString, {
|
||||||
attachments: images,
|
attachments: images,
|
||||||
replyingto: replying,
|
replyingto: replying,
|
||||||
});
|
});
|
||||||
|
@ -129,11 +129,14 @@ async function enter(event) {
|
||||||
images.pop();
|
images.pop();
|
||||||
pasteimage.removeChild(imageshtml.pop());
|
pasteimage.removeChild(imageshtml.pop());
|
||||||
}
|
}
|
||||||
typebox.value = "";
|
typebox.innerHTML = "";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const typebox = document.getElementById("typebox");
|
const typebox = document.getElementById("typebox");
|
||||||
|
const markdown = new MarkDown("", thisuser);
|
||||||
|
markdown.giveBox(typebox);
|
||||||
|
typebox["markdown"] = markdown;
|
||||||
typebox.addEventListener("keyup", enter);
|
typebox.addEventListener("keyup", enter);
|
||||||
typebox.addEventListener("keydown", event => {
|
typebox.addEventListener("keydown", event => {
|
||||||
if (event.key === "Enter" && !event.shiftKey)
|
if (event.key === "Enter" && !event.shiftKey)
|
||||||
|
@ -149,6 +152,7 @@ function getguildinfo() {
|
||||||
const images = [];
|
const images = [];
|
||||||
const imageshtml = [];
|
const imageshtml = [];
|
||||||
import { File } from "./file.js";
|
import { File } from "./file.js";
|
||||||
|
import { MarkDown } from "./markdown.js";
|
||||||
document.addEventListener('paste', async (e) => {
|
document.addEventListener('paste', async (e) => {
|
||||||
Array.from(e.clipboardData.files).forEach(async (f) => {
|
Array.from(e.clipboardData.files).forEach(async (f) => {
|
||||||
const file = File.initFromBlob(f);
|
const file = File.initFromBlob(f);
|
||||||
|
@ -164,6 +168,14 @@ function userSettings() {
|
||||||
thisuser.usersettings.show();
|
thisuser.usersettings.show();
|
||||||
}
|
}
|
||||||
document.getElementById("settings").onclick = userSettings;
|
document.getElementById("settings").onclick = userSettings;
|
||||||
|
function userConnections() {
|
||||||
|
thisuser.userConnections.show();
|
||||||
|
}
|
||||||
|
document.getElementById("connections").onclick = userConnections;
|
||||||
|
function devPortal() {
|
||||||
|
thisuser.devPortal.show();
|
||||||
|
}
|
||||||
|
document.getElementById("dev-portal").onclick = devPortal;
|
||||||
if (mobile) {
|
if (mobile) {
|
||||||
document.getElementById("channelw").onclick = function () {
|
document.getElementById("channelw").onclick = function () {
|
||||||
document.getElementById("channels").parentNode.classList.add("collapse");
|
document.getElementById("channels").parentNode.classList.add("collapse");
|
||||||
|
|
|
@ -4,6 +4,8 @@ import { Voice } from "./audio.js";
|
||||||
import { User } from "./user.js";
|
import { User } from "./user.js";
|
||||||
import { Fullscreen } from "./fullscreen.js";
|
import { Fullscreen } from "./fullscreen.js";
|
||||||
import { setTheme } from "./login.js";
|
import { setTheme } from "./login.js";
|
||||||
|
import { SnowFlake } from "./snowflake.js";
|
||||||
|
import { Message } from "./message.js";
|
||||||
const wsCodesRetry = new Set([4000, 4003, 4005, 4007, 4008, 4009]);
|
const wsCodesRetry = new Set([4000, 4003, 4005, 4007, 4008, 4009]);
|
||||||
class Localuser {
|
class Localuser {
|
||||||
packets;
|
packets;
|
||||||
|
@ -14,6 +16,8 @@ class Localuser {
|
||||||
info;
|
info;
|
||||||
headers;
|
headers;
|
||||||
usersettings;
|
usersettings;
|
||||||
|
userConnections;
|
||||||
|
devPortal;
|
||||||
ready;
|
ready;
|
||||||
guilds;
|
guilds;
|
||||||
guildids;
|
guildids;
|
||||||
|
@ -41,14 +45,14 @@ class Localuser {
|
||||||
this.initialized = true;
|
this.initialized = true;
|
||||||
this.ready = ready;
|
this.ready = ready;
|
||||||
this.guilds = [];
|
this.guilds = [];
|
||||||
this.guildids = {};
|
this.guildids = new Map();
|
||||||
this.user = new User(ready.d.user, this);
|
this.user = new User(ready.d.user, this);
|
||||||
this.userinfo.username = this.user.username;
|
this.userinfo.username = this.user.username;
|
||||||
this.userinfo.pfpsrc = this.user.getpfpsrc();
|
this.userinfo.pfpsrc = this.user.getpfpsrc();
|
||||||
this.status = this.ready.d.user_settings.status;
|
this.status = this.ready.d.user_settings.status;
|
||||||
this.channelfocus = null;
|
this.channelfocus = null;
|
||||||
this.lookingguild = null;
|
this.lookingguild = null;
|
||||||
this.guildhtml = {};
|
this.guildhtml = new Map();
|
||||||
const members = {};
|
const members = {};
|
||||||
for (const thing of ready.d.merged_members) {
|
for (const thing of ready.d.merged_members) {
|
||||||
members[thing[0].guild_id] = thing[0];
|
members[thing[0].guild_id] = thing[0];
|
||||||
|
@ -56,12 +60,12 @@ class Localuser {
|
||||||
for (const thing of ready.d.guilds) {
|
for (const thing of ready.d.guilds) {
|
||||||
const temp = new Guild(thing, this, members[thing.id]);
|
const temp = new Guild(thing, this, members[thing.id]);
|
||||||
this.guilds.push(temp);
|
this.guilds.push(temp);
|
||||||
this.guildids[temp.id] = temp;
|
this.guildids[temp.id.id] = temp;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const temp = new Direct(ready.d.private_channels, this);
|
const temp = new Direct(ready.d.private_channels, this);
|
||||||
this.guilds.push(temp);
|
this.guilds.push(temp);
|
||||||
this.guildids[temp.id] = temp;
|
this.guildids[temp.id.id] = temp;
|
||||||
}
|
}
|
||||||
console.log(ready.d.user_guild_settings.entries);
|
console.log(ready.d.user_guild_settings.entries);
|
||||||
for (const thing of ready.d.user_guild_settings.entries) {
|
for (const thing of ready.d.user_guild_settings.entries) {
|
||||||
|
@ -77,14 +81,16 @@ class Localuser {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const guildid = guild.id;
|
const guildid = guild.id;
|
||||||
this.guildids[guildid].channelids[thing.channel_id].readStateInfo(thing);
|
this.guildids[guildid.id].channelids[thing.channel_id].readStateInfo(thing);
|
||||||
}
|
}
|
||||||
this.typing = [];
|
this.typing = [];
|
||||||
}
|
}
|
||||||
outoffocus() {
|
outoffocus() {
|
||||||
document.getElementById("servers").textContent = "";
|
document.getElementById("servers").textContent = "";
|
||||||
document.getElementById("channels").textContent = "";
|
document.getElementById("channels").textContent = "";
|
||||||
|
if (this.channelfocus) {
|
||||||
this.channelfocus.infinite.delete();
|
this.channelfocus.infinite.delete();
|
||||||
|
}
|
||||||
this.lookingguild = null;
|
this.lookingguild = null;
|
||||||
this.channelfocus = null;
|
this.channelfocus = null;
|
||||||
}
|
}
|
||||||
|
@ -93,7 +99,7 @@ class Localuser {
|
||||||
clearInterval(this.wsinterval);
|
clearInterval(this.wsinterval);
|
||||||
this.outoffocus();
|
this.outoffocus();
|
||||||
this.guilds = [];
|
this.guilds = [];
|
||||||
this.guildids = {};
|
this.guildids = new Map();
|
||||||
this.ws.close(4000);
|
this.ws.close(4000);
|
||||||
}
|
}
|
||||||
async initwebsocket() {
|
async initwebsocket() {
|
||||||
|
@ -124,7 +130,6 @@ class Localuser {
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
this.ws.addEventListener('message', (event) => {
|
this.ws.addEventListener('message', (event) => {
|
||||||
try {
|
|
||||||
const temp = JSON.parse(event.data);
|
const temp = JSON.parse(event.data);
|
||||||
console.log(temp);
|
console.log(temp);
|
||||||
if (temp.op == 0) {
|
if (temp.op == 0) {
|
||||||
|
@ -136,7 +141,7 @@ class Localuser {
|
||||||
break;
|
break;
|
||||||
case "MESSAGE_DELETE":
|
case "MESSAGE_DELETE":
|
||||||
console.log(temp.d);
|
console.log(temp.d);
|
||||||
this.guildids[temp.d.guild_id].channelids[temp.d.channel_id].messageids[temp.d.id].deleteEvent();
|
SnowFlake.getSnowFlakeFromID(temp.d.id, Message).getObject().deleteEvent();
|
||||||
break;
|
break;
|
||||||
case "READY":
|
case "READY":
|
||||||
this.gottenReady(temp);
|
this.gottenReady(temp);
|
||||||
|
@ -144,7 +149,7 @@ class Localuser {
|
||||||
returny();
|
returny();
|
||||||
break;
|
break;
|
||||||
case "MESSAGE_UPDATE":
|
case "MESSAGE_UPDATE":
|
||||||
const message = this.resolveChannelFromID(temp.d.channel_id).messageids[temp.d.id];
|
const message = SnowFlake.getSnowFlakeFromID(temp.d.id, Message).getObject();
|
||||||
message.giveData(temp.d);
|
message.giveData(temp.d);
|
||||||
break;
|
break;
|
||||||
case "TYPING_START":
|
case "TYPING_START":
|
||||||
|
@ -154,7 +159,7 @@ class Localuser {
|
||||||
break;
|
break;
|
||||||
case "USER_UPDATE":
|
case "USER_UPDATE":
|
||||||
if (this.initialized) {
|
if (this.initialized) {
|
||||||
const users = User.userids[temp.d.id];
|
const users = SnowFlake.getSnowFlakeFromID(temp.d.id, User).getObject();
|
||||||
console.log(users, temp.d.id);
|
console.log(users, temp.d.id);
|
||||||
if (users) {
|
if (users) {
|
||||||
users.userupdate(temp.d);
|
users.userupdate(temp.d);
|
||||||
|
@ -188,7 +193,7 @@ class Localuser {
|
||||||
{
|
{
|
||||||
const guildy = new Guild(temp.d, this, this.user);
|
const guildy = new Guild(temp.d, this, this.user);
|
||||||
this.guilds.push(guildy);
|
this.guilds.push(guildy);
|
||||||
this.guildids[guildy.id] = guildy;
|
this.guildids[guildy.id.id] = guildy;
|
||||||
document.getElementById("servers").insertBefore(guildy.generateGuildIcon(), document.getElementById("bottomseparator"));
|
document.getElementById("servers").insertBefore(guildy.generateGuildIcon(), document.getElementById("bottomseparator"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -205,10 +210,6 @@ class Localuser {
|
||||||
else if (temp.op != 11) {
|
else if (temp.op != 11) {
|
||||||
this.packets++;
|
this.packets++;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
this.ws.addEventListener("close", event => {
|
this.ws.addEventListener("close", event => {
|
||||||
console.log("WebSocket closed with code " + event.code);
|
console.log("WebSocket closed with code " + event.code);
|
||||||
|
@ -249,15 +250,15 @@ class Localuser {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
updateChannel(JSON) {
|
updateChannel(JSON) {
|
||||||
this.guildids[JSON.guild_id].updateChannel(JSON);
|
SnowFlake.getSnowFlakeFromID(JSON.guild_id, Guild).getObject().updateChannel(JSON);
|
||||||
if (JSON.guild_id === this.lookingguild.id) {
|
if (JSON.guild_id === this.lookingguild.id.id) {
|
||||||
this.loadGuild(JSON.guild_id);
|
this.loadGuild(JSON.guild_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
createChannel(JSON) {
|
createChannel(JSON) {
|
||||||
JSON.guild_id ??= "@me";
|
JSON.guild_id ??= "@me";
|
||||||
this.guildids[JSON.guild_id].createChannelpac(JSON);
|
SnowFlake.getSnowFlakeFromID(JSON.guild_id, Guild).getObject().createChannelpac(JSON);
|
||||||
if (JSON.guild_id === this.lookingguild.id) {
|
if (JSON.guild_id === this.lookingguild.id.id) {
|
||||||
this.loadGuild(JSON.guild_id);
|
this.loadGuild(JSON.guild_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -465,10 +466,10 @@ class Localuser {
|
||||||
unreads() {
|
unreads() {
|
||||||
console.log(this.guildhtml);
|
console.log(this.guildhtml);
|
||||||
for (const thing of this.guilds) {
|
for (const thing of this.guilds) {
|
||||||
if (thing.id === "@me") {
|
if (thing.id.id === "@me") {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
thing.unreads(this.guildhtml[thing.id]);
|
thing.unreads(this.guildhtml[thing.id.id]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
typingStart(typing) {
|
typingStart(typing) {
|
||||||
|
@ -506,7 +507,7 @@ class Localuser {
|
||||||
reader.readAsDataURL(file);
|
reader.readAsDataURL(file);
|
||||||
console.log(this.headers);
|
console.log(this.headers);
|
||||||
reader.onload = () => {
|
reader.onload = () => {
|
||||||
fetch(this.info.api.toString() + "/v9/users/@me", {
|
fetch(this.info.api.toString() + "/users/@me", {
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
headers: this.headers,
|
headers: this.headers,
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
|
@ -517,7 +518,7 @@ class Localuser {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
updatepronouns(pronouns) {
|
updatepronouns(pronouns) {
|
||||||
fetch(this.info.api.toString() + "/v9/users/@me/profile", {
|
fetch(this.info.api.toString() + "/users/@me/profile", {
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
headers: this.headers,
|
headers: this.headers,
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
|
@ -594,13 +595,13 @@ class Localuser {
|
||||||
newprouns = this.value;
|
newprouns = this.value;
|
||||||
regen();
|
regen();
|
||||||
}],
|
}],
|
||||||
["mdbox", "Bio:", this.user.bio, function (e) {
|
["mdbox", "Bio:", this.user.bio.rawString, function (e) {
|
||||||
console.log(this.value);
|
console.log(this.value);
|
||||||
hypouser.bio = this.value;
|
hypouser.bio = this.value;
|
||||||
newbio = this.value;
|
newbio = this.value;
|
||||||
regen();
|
regen();
|
||||||
}],
|
}],
|
||||||
["button", "update user content:", "submit", function () {
|
["button", "update user content:", "submit", () => {
|
||||||
if (file !== null) {
|
if (file !== null) {
|
||||||
this.updatepfp(file);
|
this.updatepfp(file);
|
||||||
}
|
}
|
||||||
|
@ -631,6 +632,243 @@ class Localuser {
|
||||||
newprouns = null;
|
newprouns = null;
|
||||||
newbio = null;
|
newbio = null;
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
const connectionContainer = document.createElement("div");
|
||||||
|
connectionContainer.id = "connection-container";
|
||||||
|
this.userConnections = new Fullscreen(["html",
|
||||||
|
connectionContainer
|
||||||
|
], () => { }, async () => {
|
||||||
|
connectionContainer.innerHTML = "";
|
||||||
|
const res = await fetch(this.info.api.toString() + "/v9/connections", {
|
||||||
|
headers: this.headers
|
||||||
|
});
|
||||||
|
const json = await res.json();
|
||||||
|
Object.keys(json).sort(key => json[key].enabled ? -1 : 1).forEach(key => {
|
||||||
|
const connection = json[key];
|
||||||
|
const container = document.createElement("div");
|
||||||
|
container.textContent = key.charAt(0).toUpperCase() + key.slice(1);
|
||||||
|
if (connection.enabled) {
|
||||||
|
container.addEventListener("click", async () => {
|
||||||
|
const connectionRes = await fetch(this.info.api.toString() + "/v9/connections/" + key + "/authorize", {
|
||||||
|
headers: this.headers
|
||||||
|
});
|
||||||
|
const connectionJSON = await connectionRes.json();
|
||||||
|
window.open(connectionJSON.url, "_blank", "noopener noreferrer");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
container.classList.add("disabled");
|
||||||
|
container.title = "This connection has been disabled server-side.";
|
||||||
|
}
|
||||||
|
connectionContainer.appendChild(container);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
let appName = "";
|
||||||
|
const appListContainer = document.createElement("div");
|
||||||
|
appListContainer.id = "app-list-container";
|
||||||
|
this.devPortal = new Fullscreen(["vdiv",
|
||||||
|
["hdiv",
|
||||||
|
["textbox", "Name:", appName, event => {
|
||||||
|
appName = event.target.value;
|
||||||
|
}],
|
||||||
|
["button",
|
||||||
|
"",
|
||||||
|
"Create application",
|
||||||
|
async () => {
|
||||||
|
if (appName.trim().length == 0)
|
||||||
|
return alert("Please enter a name for the application.");
|
||||||
|
const res = await fetch(this.info.api.toString() + "/v9/applications", {
|
||||||
|
method: "POST",
|
||||||
|
headers: this.headers,
|
||||||
|
body: JSON.stringify({
|
||||||
|
name: appName
|
||||||
|
})
|
||||||
|
});
|
||||||
|
const json = await res.json();
|
||||||
|
this.manageApplication(json.id);
|
||||||
|
this.devPortal.hide();
|
||||||
|
}
|
||||||
|
]
|
||||||
|
],
|
||||||
|
["html",
|
||||||
|
appListContainer
|
||||||
|
]
|
||||||
|
], () => { }, async () => {
|
||||||
|
appListContainer.innerHTML = "";
|
||||||
|
const res = await fetch(this.info.api.toString() + "/v9/applications", {
|
||||||
|
headers: this.headers
|
||||||
|
});
|
||||||
|
const json = await res.json();
|
||||||
|
json.forEach(application => {
|
||||||
|
const container = document.createElement("div");
|
||||||
|
if (application.cover_image) {
|
||||||
|
const cover = document.createElement("img");
|
||||||
|
cover.crossOrigin = "anonymous";
|
||||||
|
cover.src = this.info.cdn.toString() + "/app-icons/" + application.id + "/" + application.cover_image + ".png?size=256";
|
||||||
|
cover.alt = "";
|
||||||
|
cover.loading = "lazy";
|
||||||
|
container.appendChild(cover);
|
||||||
|
}
|
||||||
|
const name = document.createElement("h2");
|
||||||
|
name.textContent = application.name + (application.bot ? " (Bot)" : "");
|
||||||
|
container.appendChild(name);
|
||||||
|
container.addEventListener("click", async () => {
|
||||||
|
this.devPortal.hide();
|
||||||
|
this.manageApplication(application.id);
|
||||||
|
});
|
||||||
|
appListContainer.appendChild(container);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async manageApplication(appId = "") {
|
||||||
|
const res = await fetch(this.info.api.toString() + "/v9/applications/" + appId, {
|
||||||
|
headers: this.headers
|
||||||
|
});
|
||||||
|
const json = await res.json();
|
||||||
|
const fields = {};
|
||||||
|
const appDialog = new Fullscreen(["vdiv",
|
||||||
|
["title",
|
||||||
|
"Editing " + json.name
|
||||||
|
],
|
||||||
|
["vdiv",
|
||||||
|
["textbox", "Application name:", json.name, event => {
|
||||||
|
fields.name = event.target.value;
|
||||||
|
}],
|
||||||
|
["mdbox", "Description:", json.description, event => {
|
||||||
|
fields.description = event.target.value;
|
||||||
|
}],
|
||||||
|
["vdiv",
|
||||||
|
json.icon ? ["img", this.info.cdn.toString() + "/app-icons/" + appId + "/" + json.icon + ".png?size=128", [128, 128]] : ["text", "No icon"],
|
||||||
|
["fileupload", "Application icon:", event => {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.readAsDataURL(event.target.files[0]);
|
||||||
|
reader.onload = () => {
|
||||||
|
fields.icon = reader.result;
|
||||||
|
};
|
||||||
|
}]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
["hdiv",
|
||||||
|
["textbox", "Privacy policy URL:", json.privacy_policy_url || "", event => {
|
||||||
|
fields.privacy_policy_url = event.target.value;
|
||||||
|
}],
|
||||||
|
["textbox", "Terms of Service URL:", json.terms_of_service_url || "", event => {
|
||||||
|
fields.terms_of_service_url = event.target.value;
|
||||||
|
}]
|
||||||
|
],
|
||||||
|
["hdiv",
|
||||||
|
["checkbox", "Make bot publicly inviteable?", json.bot_public, event => {
|
||||||
|
fields.bot_public = event.target.checked;
|
||||||
|
}],
|
||||||
|
["checkbox", "Require code grant to invite the bot?", json.bot_require_code_grant, event => {
|
||||||
|
fields.bot_require_code_grant = event.target.checked;
|
||||||
|
}]
|
||||||
|
],
|
||||||
|
["hdiv",
|
||||||
|
["button",
|
||||||
|
"",
|
||||||
|
"Save changes",
|
||||||
|
async () => {
|
||||||
|
const updateRes = await fetch(this.info.api.toString() + "/v9/applications/" + appId, {
|
||||||
|
method: "PATCH",
|
||||||
|
headers: this.headers,
|
||||||
|
body: JSON.stringify(fields)
|
||||||
|
});
|
||||||
|
if (updateRes.ok)
|
||||||
|
appDialog.hide();
|
||||||
|
else {
|
||||||
|
const updateJSON = await updateRes.json();
|
||||||
|
alert("An error occurred: " + updateJSON.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
["button",
|
||||||
|
"",
|
||||||
|
(json.bot ? "Manage" : "Add") + " bot",
|
||||||
|
async () => {
|
||||||
|
if (!json.bot) {
|
||||||
|
if (!confirm("Are you sure you want to add a bot to this application? There's no going back."))
|
||||||
|
return;
|
||||||
|
const updateRes = await fetch(this.info.api.toString() + "/v9/applications/" + appId + "/bot", {
|
||||||
|
method: "POST",
|
||||||
|
headers: this.headers
|
||||||
|
});
|
||||||
|
const updateJSON = await updateRes.json();
|
||||||
|
alert("Bot token:\n" + updateJSON.token);
|
||||||
|
}
|
||||||
|
appDialog.hide();
|
||||||
|
this.manageBot(appId);
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
appDialog.show();
|
||||||
|
}
|
||||||
|
async manageBot(appId = "") {
|
||||||
|
const res = await fetch(this.info.api.toString() + "/v9/applications/" + appId, {
|
||||||
|
headers: this.headers
|
||||||
|
});
|
||||||
|
const json = await res.json();
|
||||||
|
if (!json.bot)
|
||||||
|
return alert("For some reason, this application doesn't have a bot (yet).");
|
||||||
|
const fields = {
|
||||||
|
username: json.bot.username,
|
||||||
|
avatar: json.bot.avatar ? (this.info.cdn.toString() + "/app-icons/" + appId + "/" + json.bot.avatar + ".png?size=256") : ""
|
||||||
|
};
|
||||||
|
const botDialog = new Fullscreen(["vdiv",
|
||||||
|
["title",
|
||||||
|
"Editing bot: " + json.bot.username
|
||||||
|
],
|
||||||
|
["hdiv",
|
||||||
|
["textbox", "Bot username:", json.bot.username, event => {
|
||||||
|
fields.username = event.target.value;
|
||||||
|
}],
|
||||||
|
["vdiv",
|
||||||
|
fields.avatar ? ["img", fields.avatar, [128, 128]] : ["text", "No avatar"],
|
||||||
|
["fileupload", "Bot avatar:", event => {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.readAsDataURL(event.target.files[0]);
|
||||||
|
reader.onload = () => {
|
||||||
|
fields.avatar = reader.result;
|
||||||
|
};
|
||||||
|
}]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
["hdiv",
|
||||||
|
["button",
|
||||||
|
"",
|
||||||
|
"Save changes",
|
||||||
|
async () => {
|
||||||
|
const updateRes = await fetch(this.info.api.toString() + "/v9/applications/" + appId + "/bot", {
|
||||||
|
method: "PATCH",
|
||||||
|
headers: this.headers,
|
||||||
|
body: JSON.stringify(fields)
|
||||||
|
});
|
||||||
|
if (updateRes.ok)
|
||||||
|
botDialog.hide();
|
||||||
|
else {
|
||||||
|
const updateJSON = await updateRes.json();
|
||||||
|
alert("An error occurred: " + updateJSON.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
["button",
|
||||||
|
"",
|
||||||
|
"Reset token",
|
||||||
|
async () => {
|
||||||
|
if (!confirm("Are you sure you want to reset the bot token? Your bot will stop working until you update it."))
|
||||||
|
return;
|
||||||
|
const updateRes = await fetch(this.info.api.toString() + "/v9/applications/" + appId + "/bot/reset", {
|
||||||
|
method: "POST",
|
||||||
|
headers: this.headers
|
||||||
|
});
|
||||||
|
const updateJSON = await updateRes.json();
|
||||||
|
alert("New token:\n" + updateJSON.token);
|
||||||
|
botDialog.hide();
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
botDialog.show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export { Localuser };
|
export { Localuser };
|
||||||
|
|
|
@ -1,5 +1,35 @@
|
||||||
export { markdown };
|
export { MarkDown };
|
||||||
function markdown(text, { keep = false, stdsize = false } = {}) {
|
class MarkDown {
|
||||||
|
txt;
|
||||||
|
keep;
|
||||||
|
stdsize;
|
||||||
|
owner;
|
||||||
|
info;
|
||||||
|
constructor(text, owner, { keep = false, stdsize = false } = {}) {
|
||||||
|
if ((typeof text) === (typeof "")) {
|
||||||
|
this.txt = text.split("");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.txt = text;
|
||||||
|
}
|
||||||
|
if (this.txt === undefined) {
|
||||||
|
this.txt = [];
|
||||||
|
}
|
||||||
|
this.info = owner.info;
|
||||||
|
this.keep = keep;
|
||||||
|
this.owner = owner;
|
||||||
|
this.stdsize = stdsize;
|
||||||
|
}
|
||||||
|
get rawString() {
|
||||||
|
return this.txt.join("");
|
||||||
|
}
|
||||||
|
get textContent() {
|
||||||
|
return this.makeHTML().textContent;
|
||||||
|
}
|
||||||
|
makeHTML({ keep = this.keep, stdsize = this.stdsize } = {}) {
|
||||||
|
return this.markdown(this.txt, { keep: keep, stdsize: stdsize });
|
||||||
|
}
|
||||||
|
markdown(text, { keep = false, stdsize = false } = {}) {
|
||||||
let txt;
|
let txt;
|
||||||
if ((typeof text) === (typeof "")) {
|
if ((typeof text) === (typeof "")) {
|
||||||
txt = text.split("");
|
txt = text.split("");
|
||||||
|
@ -71,9 +101,10 @@ function markdown(text, { keep = false, stdsize = false } = {}) {
|
||||||
if (keep) {
|
if (keep) {
|
||||||
element.append(keepys);
|
element.append(keepys);
|
||||||
}
|
}
|
||||||
element.appendChild(markdown(build, { keep: keep, stdsize: stdsize }));
|
element.appendChild(this.markdown(build, { keep: keep, stdsize: stdsize }));
|
||||||
span.append(element);
|
span.append(element);
|
||||||
i--;
|
i -= 1;
|
||||||
|
console.log(txt[i]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (first) {
|
if (first) {
|
||||||
|
@ -186,7 +217,7 @@ function markdown(text, { keep = false, stdsize = false } = {}) {
|
||||||
if (keep) {
|
if (keep) {
|
||||||
i.append(stars);
|
i.append(stars);
|
||||||
}
|
}
|
||||||
i.appendChild(markdown(build, { keep: keep, stdsize: stdsize }));
|
i.appendChild(this.markdown(build, { keep: keep, stdsize: stdsize }));
|
||||||
if (keep) {
|
if (keep) {
|
||||||
i.append(stars);
|
i.append(stars);
|
||||||
}
|
}
|
||||||
|
@ -197,7 +228,7 @@ function markdown(text, { keep = false, stdsize = false } = {}) {
|
||||||
if (keep) {
|
if (keep) {
|
||||||
b.append(stars);
|
b.append(stars);
|
||||||
}
|
}
|
||||||
b.appendChild(markdown(build, { keep: keep, stdsize: stdsize }));
|
b.appendChild(this.markdown(build, { keep: keep, stdsize: stdsize }));
|
||||||
if (keep) {
|
if (keep) {
|
||||||
b.append(stars);
|
b.append(stars);
|
||||||
}
|
}
|
||||||
|
@ -209,7 +240,7 @@ function markdown(text, { keep = false, stdsize = false } = {}) {
|
||||||
if (keep) {
|
if (keep) {
|
||||||
b.append(stars);
|
b.append(stars);
|
||||||
}
|
}
|
||||||
b.appendChild(markdown(build, { keep: keep, stdsize: stdsize }));
|
b.appendChild(this.markdown(build, { keep: keep, stdsize: stdsize }));
|
||||||
if (keep) {
|
if (keep) {
|
||||||
b.append(stars);
|
b.append(stars);
|
||||||
}
|
}
|
||||||
|
@ -252,7 +283,7 @@ function markdown(text, { keep = false, stdsize = false } = {}) {
|
||||||
if (keep) {
|
if (keep) {
|
||||||
i.append(underscores);
|
i.append(underscores);
|
||||||
}
|
}
|
||||||
i.appendChild(markdown(build, { keep: keep, stdsize: stdsize }));
|
i.appendChild(this.markdown(build, { keep: keep, stdsize: stdsize }));
|
||||||
if (keep) {
|
if (keep) {
|
||||||
i.append(underscores);
|
i.append(underscores);
|
||||||
}
|
}
|
||||||
|
@ -263,7 +294,7 @@ function markdown(text, { keep = false, stdsize = false } = {}) {
|
||||||
if (keep) {
|
if (keep) {
|
||||||
u.append(underscores);
|
u.append(underscores);
|
||||||
}
|
}
|
||||||
u.appendChild(markdown(build, { keep: keep, stdsize: stdsize }));
|
u.appendChild(this.markdown(build, { keep: keep, stdsize: stdsize }));
|
||||||
if (keep) {
|
if (keep) {
|
||||||
u.append(underscores);
|
u.append(underscores);
|
||||||
}
|
}
|
||||||
|
@ -275,7 +306,7 @@ function markdown(text, { keep = false, stdsize = false } = {}) {
|
||||||
if (keep) {
|
if (keep) {
|
||||||
i.append(underscores);
|
i.append(underscores);
|
||||||
}
|
}
|
||||||
i.appendChild(markdown(build, { keep: keep, stdsize: stdsize }));
|
i.appendChild(this.markdown(build, { keep: keep, stdsize: stdsize }));
|
||||||
if (keep) {
|
if (keep) {
|
||||||
i.append(underscores);
|
i.append(underscores);
|
||||||
}
|
}
|
||||||
|
@ -305,14 +336,14 @@ function markdown(text, { keep = false, stdsize = false } = {}) {
|
||||||
}
|
}
|
||||||
if (find === count) {
|
if (find === count) {
|
||||||
appendcurrent();
|
appendcurrent();
|
||||||
i = j;
|
i = j - 1;
|
||||||
const tildes = "~~";
|
const tildes = "~~";
|
||||||
if (count === 2) {
|
if (count === 2) {
|
||||||
const s = document.createElement("s");
|
const s = document.createElement("s");
|
||||||
if (keep) {
|
if (keep) {
|
||||||
s.append(tildes);
|
s.append(tildes);
|
||||||
}
|
}
|
||||||
s.appendChild(markdown(build, { keep: keep, stdsize: stdsize }));
|
s.appendChild(this.markdown(build, { keep: keep, stdsize: stdsize }));
|
||||||
if (keep) {
|
if (keep) {
|
||||||
s.append(tildes);
|
s.append(tildes);
|
||||||
}
|
}
|
||||||
|
@ -340,16 +371,16 @@ function markdown(text, { keep = false, stdsize = false } = {}) {
|
||||||
}
|
}
|
||||||
if (find === count) {
|
if (find === count) {
|
||||||
appendcurrent();
|
appendcurrent();
|
||||||
i = j;
|
i = j - 1;
|
||||||
const pipes = "||";
|
const pipes = "||";
|
||||||
if (count === 2) {
|
if (count === 2) {
|
||||||
const j = document.createElement("j");
|
const j = document.createElement("j");
|
||||||
if (keep) {
|
if (keep) {
|
||||||
j.append(pipes);
|
j.append(pipes);
|
||||||
}
|
}
|
||||||
j.appendChild(markdown(build, { keep: keep, stdsize: stdsize }));
|
j.appendChild(this.markdown(build, { keep: keep, stdsize: stdsize }));
|
||||||
j.classList.add("spoiler");
|
j.classList.add("spoiler");
|
||||||
j.onclick = markdown.unspoil;
|
j.onclick = MarkDown.unspoil;
|
||||||
if (keep) {
|
if (keep) {
|
||||||
j.append(pipes);
|
j.append(pipes);
|
||||||
}
|
}
|
||||||
|
@ -414,20 +445,18 @@ function markdown(text, { keep = false, stdsize = false } = {}) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (found) {
|
if (found) {
|
||||||
const parts = build.join("").match(/^<(a)?:\w+:(\d{10,30})>$/);
|
const buildjoin = build.join("");
|
||||||
|
const parts = buildjoin.match(/^<(a)?:\w+:(\d{10,30})>$/);
|
||||||
if (parts && parts[2]) {
|
if (parts && parts[2]) {
|
||||||
appendcurrent();
|
appendcurrent();
|
||||||
i = j;
|
i = j;
|
||||||
console.log(typeof txt, txt);
|
const isEmojiOnly = txt.join("").trim() === buildjoin.trim();
|
||||||
const isEmojiOnly = txt.join("").trim() === build.join("").trim();
|
|
||||||
const emojiElem = document.createElement("img");
|
const emojiElem = document.createElement("img");
|
||||||
emojiElem.classList.add("md-emoji");
|
emojiElem.classList.add("md-emoji");
|
||||||
emojiElem.width = isEmojiOnly ? 48 : 22;
|
emojiElem.classList.add(isEmojiOnly ? "bigemoji" : "smallemoji");
|
||||||
emojiElem.height = isEmojiOnly ? 48 : 22;
|
|
||||||
emojiElem.crossOrigin = "anonymous";
|
emojiElem.crossOrigin = "anonymous";
|
||||||
//emojiElem.src=this.info.cdn.toString() + "/emojis/" + parts[2] + "." + (parts[1] ? "gif" : "png") + "?size=32";
|
emojiElem.src = this.info.cdn.toString() + "emojis/" + parts[2] + "." + (parts[1] ? "gif" : "png") + "?size=32";
|
||||||
//must uncomment later
|
emojiElem.alt = buildjoin;
|
||||||
emojiElem.alt = "";
|
|
||||||
emojiElem.loading = "lazy";
|
emojiElem.loading = "lazy";
|
||||||
span.appendChild(emojiElem);
|
span.appendChild(emojiElem);
|
||||||
continue;
|
continue;
|
||||||
|
@ -438,9 +467,89 @@ function markdown(text, { keep = false, stdsize = false } = {}) {
|
||||||
}
|
}
|
||||||
appendcurrent();
|
appendcurrent();
|
||||||
return span;
|
return span;
|
||||||
}
|
}
|
||||||
markdown.unspoil = function (e) {
|
static unspoil(e) {
|
||||||
//console.log("undone")
|
|
||||||
e.target.classList.remove("spoiler");
|
e.target.classList.remove("spoiler");
|
||||||
e.target.classList.add("unspoiled");
|
e.target.classList.add("unspoiled");
|
||||||
};
|
}
|
||||||
|
giveBox(box) {
|
||||||
|
box.onkeydown = _ => {
|
||||||
|
//console.log(_);
|
||||||
|
};
|
||||||
|
let prevcontent = "";
|
||||||
|
box.onkeyup = _ => {
|
||||||
|
const content = MarkDown.gatherBoxText(box);
|
||||||
|
if (content !== prevcontent) {
|
||||||
|
prevcontent = content;
|
||||||
|
this.txt = content.split("");
|
||||||
|
this.boxupdate(box);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
box.onpaste = _ => {
|
||||||
|
console.log(_.clipboardData.types);
|
||||||
|
const data = _.clipboardData.getData("text");
|
||||||
|
document.execCommand('insertHTML', false, data);
|
||||||
|
_.preventDefault();
|
||||||
|
box.onkeyup(new KeyboardEvent("_"));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
boxupdate(box) {
|
||||||
|
var restore = saveCaretPosition(box);
|
||||||
|
box.innerHTML = "";
|
||||||
|
box.append(this.makeHTML({ keep: true }));
|
||||||
|
restore();
|
||||||
|
}
|
||||||
|
static gatherBoxText(element) {
|
||||||
|
const children = element.childNodes;
|
||||||
|
if (element.tagName.toLowerCase() === "img") {
|
||||||
|
return element.alt;
|
||||||
|
}
|
||||||
|
if (element.tagName.toLowerCase() === "br") {
|
||||||
|
return "\n";
|
||||||
|
}
|
||||||
|
if (children.length !== 0) {
|
||||||
|
let build = "";
|
||||||
|
for (const thing of children) {
|
||||||
|
if (thing instanceof Text) {
|
||||||
|
const text = thing.textContent;
|
||||||
|
build += text;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const text = this.gatherBoxText(thing);
|
||||||
|
if (text) {
|
||||||
|
build += text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return build;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//solution from https://stackoverflow.com/questions/4576694/saving-and-restoring-caret-position-for-contenteditable-div
|
||||||
|
function saveCaretPosition(context) {
|
||||||
|
var selection = window.getSelection();
|
||||||
|
var range = selection.getRangeAt(0);
|
||||||
|
range.setStart(context, 0);
|
||||||
|
var len = range.toString().length;
|
||||||
|
return function restore() {
|
||||||
|
var pos = getTextNodeAtPosition(context, len);
|
||||||
|
selection.removeAllRanges();
|
||||||
|
var range = new Range();
|
||||||
|
range.setStart(pos.node, pos.position);
|
||||||
|
selection.addRange(range);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function getTextNodeAtPosition(root, index) {
|
||||||
|
const NODE_TYPE = NodeFilter.SHOW_TEXT;
|
||||||
|
var treeWalker = document.createTreeWalker(root, NODE_TYPE, function next(elem) {
|
||||||
|
if (index > elem.textContent.length) {
|
||||||
|
index -= elem.textContent.length;
|
||||||
|
return NodeFilter.FILTER_REJECT;
|
||||||
|
}
|
||||||
|
return NodeFilter.FILTER_ACCEPT;
|
||||||
|
});
|
||||||
|
var c = treeWalker.nextNode();
|
||||||
|
return {
|
||||||
|
node: c ? c : root,
|
||||||
|
position: index
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import { User } from "./user.js";
|
import { User } from "./user.js";
|
||||||
|
import { Role } from "./role.js";
|
||||||
import { Guild } from "./guild.js";
|
import { Guild } from "./guild.js";
|
||||||
import { Contextmenu } from "./contextmenu.js";
|
import { Contextmenu } from "./contextmenu.js";
|
||||||
|
import { SnowFlake } from "./snowflake.js";
|
||||||
class Member {
|
class Member {
|
||||||
static already = {};
|
static already = {};
|
||||||
owner;
|
owner;
|
||||||
|
@ -39,7 +41,7 @@ class Member {
|
||||||
}
|
}
|
||||||
if (thing === "roles") {
|
if (thing === "roles") {
|
||||||
for (const strrole of membery["roles"]) {
|
for (const strrole of membery["roles"]) {
|
||||||
const role = this.guild.getRole(strrole);
|
const role = SnowFlake.getSnowFlakeFromID(strrole, Role).getObject();
|
||||||
this.roles.push(role);
|
this.roles.push(role);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
@ -67,50 +69,50 @@ class Member {
|
||||||
console.error(guild);
|
console.error(guild);
|
||||||
}
|
}
|
||||||
let user;
|
let user;
|
||||||
let id = "";
|
let id;
|
||||||
if (unkown instanceof User) {
|
if (unkown instanceof User) {
|
||||||
user = unkown;
|
user = unkown;
|
||||||
id = user.id;
|
id = user.id;
|
||||||
}
|
}
|
||||||
else if (typeof unkown === typeof "") {
|
else if (typeof unkown === typeof "") {
|
||||||
id = unkown;
|
id = new SnowFlake(unkown, undefined);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return new Member(unkown, guild);
|
return new Member(unkown, guild);
|
||||||
}
|
}
|
||||||
if (guild.id === "@me") {
|
if (guild.id.id === "@me") {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (!Member.already[guild.id]) {
|
if (!Member.already[guild.id.id]) {
|
||||||
Member.already[guild.id] = {};
|
Member.already[guild.id.id] = {};
|
||||||
}
|
}
|
||||||
else if (Member.already[guild.id][id]) {
|
else if (Member.already[guild.id.id][id]) {
|
||||||
const memb = Member.already[guild.id][id];
|
const memb = Member.already[guild.id.id][id];
|
||||||
if (memb instanceof Promise) {
|
if (memb instanceof Promise) {
|
||||||
return await memb;
|
return await memb;
|
||||||
}
|
}
|
||||||
return memb;
|
return memb;
|
||||||
}
|
}
|
||||||
const promoise = fetch(guild.info.api.toString() + "/v9/users/" + id + "/profile?with_mutual_guilds=true&with_mutual_friends_count=true&guild_id=" + guild.id, { headers: guild.headers }).then(_ => _.json()).then(json => {
|
const promoise = fetch(guild.info.api.toString() + "/users/" + id + "/profile?with_mutual_guilds=true&with_mutual_friends_count=true&guild_id=" + guild.id, { headers: guild.headers }).then(_ => _.json()).then(json => {
|
||||||
const memb = new Member(json, guild);
|
const memb = new Member(json, guild);
|
||||||
Member.already[guild.id][id] = memb;
|
Member.already[guild.id.id][id] = memb;
|
||||||
console.log("resolved");
|
console.log("resolved");
|
||||||
return memb;
|
return memb;
|
||||||
});
|
});
|
||||||
Member.already[guild.id][id] = promoise;
|
Member.already[guild.id.id][id] = promoise;
|
||||||
try {
|
try {
|
||||||
return await promoise;
|
return await promoise;
|
||||||
}
|
}
|
||||||
catch (_) {
|
catch (_) {
|
||||||
const memb = new Member(user, guild, true);
|
const memb = new Member(user, guild, true);
|
||||||
Member.already[guild.id][id] = memb;
|
Member.already[guild.id.id][id] = memb;
|
||||||
return memb;
|
return memb;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hasRole(ID) {
|
hasRole(ID) {
|
||||||
console.log(this.roles, ID);
|
console.log(this.roles, ID);
|
||||||
for (const thing of this.roles) {
|
for (const thing of this.roles) {
|
||||||
if (thing.id === ID) {
|
if (thing.id.id === ID) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,7 +133,7 @@ class Member {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this.guild.properties.owner_id === this.user.id;
|
return this.guild.properties.owner_id === this.user.id.id;
|
||||||
}
|
}
|
||||||
bind(html) {
|
bind(html) {
|
||||||
if (html.tagName === "SPAN") {
|
if (html.tagName === "SPAN") {
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import { Contextmenu } from "./contextmenu.js";
|
import { Contextmenu } from "./contextmenu.js";
|
||||||
import { User } from "./user.js";
|
import { User } from "./user.js";
|
||||||
import { Member } from "./member.js";
|
import { Member } from "./member.js";
|
||||||
import { markdown } from "./markdown.js";
|
import { MarkDown } from "./markdown.js";
|
||||||
import { Embed } from "./embed.js";
|
import { Embed } from "./embed.js";
|
||||||
import { File } from "./file.js";
|
import { File } from "./file.js";
|
||||||
|
import { SnowFlake } from "./snowflake.js";
|
||||||
class Message {
|
class Message {
|
||||||
static contextmenu = new Contextmenu("message menu");
|
static contextmenu = new Contextmenu("message menu");
|
||||||
owner;
|
owner;
|
||||||
|
@ -33,17 +34,19 @@ class Message {
|
||||||
}
|
}
|
||||||
static setupcmenu() {
|
static setupcmenu() {
|
||||||
Message.contextmenu.addbutton("Copy raw text", function () {
|
Message.contextmenu.addbutton("Copy raw text", function () {
|
||||||
navigator.clipboard.writeText(this.content);
|
navigator.clipboard.writeText(this.content.rawString);
|
||||||
});
|
});
|
||||||
Message.contextmenu.addbutton("Reply", function (div) {
|
Message.contextmenu.addbutton("Reply", function (div) {
|
||||||
this.channel.setReplying(this);
|
this.channel.setReplying(this);
|
||||||
});
|
});
|
||||||
Message.contextmenu.addbutton("Copy message id", function () {
|
Message.contextmenu.addbutton("Copy message id", function () {
|
||||||
navigator.clipboard.writeText(this.id);
|
navigator.clipboard.writeText(this.id.id);
|
||||||
});
|
});
|
||||||
Message.contextmenu.addbutton("Edit", function () {
|
Message.contextmenu.addbutton("Edit", function () {
|
||||||
this.channel.editing = this;
|
this.channel.editing = this;
|
||||||
document.getElementById("typebox").value = this.content;
|
const markdown = (document.getElementById("typebox"))["markdown"];
|
||||||
|
markdown.txt = this.content.rawString;
|
||||||
|
markdown.boxupdate(document.getElementById("typebox"));
|
||||||
}, null, _ => { return _.author.id === _.localuser.user.id; });
|
}, null, _ => { return _.author.id === _.localuser.user.id; });
|
||||||
Message.contextmenu.addbutton("Delete message", function () {
|
Message.contextmenu.addbutton("Delete message", function () {
|
||||||
this.delete();
|
this.delete();
|
||||||
|
@ -63,6 +66,14 @@ class Message {
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
else if (thing === "content") {
|
||||||
|
this.content = new MarkDown(messagejson[thing], this.channel);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (thing === "id") {
|
||||||
|
this.id = new SnowFlake(messagejson.id, this);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
this[thing] = messagejson[thing];
|
this[thing] = messagejson[thing];
|
||||||
}
|
}
|
||||||
for (const thing in this.embeds) {
|
for (const thing in this.embeds) {
|
||||||
|
@ -126,14 +137,14 @@ class Message {
|
||||||
return build;
|
return build;
|
||||||
}
|
}
|
||||||
async edit(content) {
|
async edit(content) {
|
||||||
return await fetch(this.info.api.toString() + "/channels/" + this.channel.id + "/messages/" + this.id, {
|
return await fetch(this.info.api.toString() + "/channels/" + this.channel.id + "/messages/" + this.id.id, {
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
headers: this.headers,
|
headers: this.headers,
|
||||||
body: JSON.stringify({ content: content })
|
body: JSON.stringify({ content: content })
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
delete() {
|
delete() {
|
||||||
fetch(`${this.info.api.toString()}/channels/${this.channel.id}/messages/${this.id}`, {
|
fetch(`${this.info.api.toString()}/channels/${this.channel.id}/messages/${this.id.id}`, {
|
||||||
headers: this.headers,
|
headers: this.headers,
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
});
|
});
|
||||||
|
@ -143,19 +154,22 @@ class Message {
|
||||||
this.div.innerHTML = "";
|
this.div.innerHTML = "";
|
||||||
this.div = null;
|
this.div = null;
|
||||||
}
|
}
|
||||||
const prev = this.channel.idToPrev[this.id];
|
const prev = this.channel.idToPrev[this.id.id];
|
||||||
const next = this.channel.idToNext[this.id];
|
const next = this.channel.idToNext[this.id.id];
|
||||||
this.channel.idToNext[prev] = next;
|
this.channel.idToNext[prev] = next;
|
||||||
this.channel.idToPrev[next] = prev;
|
this.channel.idToPrev[next] = prev;
|
||||||
delete this.channel.messageids[this.id];
|
delete this.channel.messageids[this.id.id];
|
||||||
const regen = this.channel.messageids[prev];
|
const regen = this.channel.messageids[prev];
|
||||||
if (regen) {
|
if (regen) {
|
||||||
regen.generateMessage();
|
regen.generateMessage();
|
||||||
}
|
}
|
||||||
|
if (this.channel.lastmessage === this) {
|
||||||
|
this.channel.lastmessage = this.channel.messageids[prev];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
generateMessage(premessage = null) {
|
generateMessage(premessage = null) {
|
||||||
if (!premessage) {
|
if (!premessage) {
|
||||||
premessage = this.channel.messageids[this.channel.idToNext[this.id]];
|
premessage = this.channel.messageids[this.channel.idToNext[this.id.id]];
|
||||||
}
|
}
|
||||||
const div = this.div;
|
const div = this.div;
|
||||||
if (this === this.channel.replyingto) {
|
if (this === this.channel.replyingto) {
|
||||||
|
@ -204,7 +218,7 @@ class Message {
|
||||||
replyline.classList.add("replyflex");
|
replyline.classList.add("replyflex");
|
||||||
this.channel.getmessage(this.message_reference.message_id).then(message => {
|
this.channel.getmessage(this.message_reference.message_id).then(message => {
|
||||||
const author = message.author;
|
const author = message.author;
|
||||||
reply.appendChild(markdown(message.content, { stdsize: true }));
|
reply.appendChild(message.content.makeHTML({ stdsize: true }));
|
||||||
minipfp.src = author.getpfpsrc();
|
minipfp.src = author.getpfpsrc();
|
||||||
author.bind(minipfp);
|
author.bind(minipfp);
|
||||||
username.textContent = author.username;
|
username.textContent = author.username;
|
||||||
|
@ -266,7 +280,7 @@ class Message {
|
||||||
else {
|
else {
|
||||||
div.classList.remove("topMessage");
|
div.classList.remove("topMessage");
|
||||||
}
|
}
|
||||||
const messaged = markdown(this.content);
|
const messaged = this.content.makeHTML();
|
||||||
div["txt"] = messaged;
|
div["txt"] = messaged;
|
||||||
const messagedwrap = document.createElement("div");
|
const messagedwrap = document.createElement("div");
|
||||||
messagedwrap.classList.add("flexttb");
|
messagedwrap.classList.add("flexttb");
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
export { Role };
|
export { Role };
|
||||||
import { Permissions } from "./permissions.js";
|
import { Permissions } from "./permissions.js";
|
||||||
|
import { SnowFlake } from "./snowflake.js";
|
||||||
class Role {
|
class Role {
|
||||||
permissions;
|
permissions;
|
||||||
owner;
|
owner;
|
||||||
|
@ -16,6 +17,10 @@ class Role {
|
||||||
this.headers = owner.headers;
|
this.headers = owner.headers;
|
||||||
this.info = owner.info;
|
this.info = owner.info;
|
||||||
for (const thing of Object.keys(JSON)) {
|
for (const thing of Object.keys(JSON)) {
|
||||||
|
if (thing === "id") {
|
||||||
|
this.id = new SnowFlake(JSON.id, this);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
this[thing] = JSON[thing];
|
this[thing] = JSON[thing];
|
||||||
}
|
}
|
||||||
this.permissions = new Permissions(JSON.permissions);
|
this.permissions = new Permissions(JSON.permissions);
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
import { Permissions } from "./permissions.js";
|
import { Permissions } from "./permissions.js";
|
||||||
|
import { SnowFlake } from "./snowflake.js";
|
||||||
|
import { Role } from "./role.js";
|
||||||
class Buttons {
|
class Buttons {
|
||||||
name;
|
name;
|
||||||
buttons;
|
buttons;
|
||||||
|
@ -154,16 +156,17 @@ class RoleList extends Buttons {
|
||||||
options.addPermissionToggle(thing, this.permission); //
|
options.addPermissionToggle(thing, this.permission); //
|
||||||
}
|
}
|
||||||
for (const i of permissions) {
|
for (const i of permissions) {
|
||||||
this.buttons.push([guild.getRole(i[0]).name, i[0]]); //
|
console.log(i);
|
||||||
|
this.buttons.push([i[0].getObject().name, i[0].id]); //
|
||||||
}
|
}
|
||||||
this.options = options;
|
this.options = options;
|
||||||
}
|
}
|
||||||
handleString(str) {
|
handleString(str) {
|
||||||
this.curid = str;
|
this.curid = str;
|
||||||
const perm = this.permissions.find(_ => _[0] === str)[1];
|
const perm = this.permissions.find(_ => _[0].id === str)[1];
|
||||||
this.permission.deny = perm.deny;
|
this.permission.deny = perm.deny;
|
||||||
this.permission.allow = perm.allow;
|
this.permission.allow = perm.allow;
|
||||||
this.options.name = this.guild.getRole(str).name;
|
this.options.name = SnowFlake.getSnowFlakeFromID(str, Role).getObject().name;
|
||||||
this.options.haschanged = false;
|
this.options.haschanged = false;
|
||||||
return this.options.generateHTML();
|
return this.options.generateHTML();
|
||||||
}
|
}
|
||||||
|
|
51
.dist/snowflake.js
Normal file
51
.dist/snowflake.js
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
class SnowFlake {
|
||||||
|
id;
|
||||||
|
static SnowFlakes = new Map();
|
||||||
|
static FinalizationRegistry = new FinalizationRegistry((id) => {
|
||||||
|
SnowFlake.SnowFlakes.delete(id);
|
||||||
|
});
|
||||||
|
obj;
|
||||||
|
constructor(id, obj) {
|
||||||
|
if (!obj) {
|
||||||
|
this.id = id;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!SnowFlake.SnowFlakes.get(obj.constructor)) {
|
||||||
|
SnowFlake.SnowFlakes.set(obj.constructor, new Map());
|
||||||
|
}
|
||||||
|
if (SnowFlake.SnowFlakes.get(obj.constructor).get(id)) {
|
||||||
|
const snowflake = SnowFlake.SnowFlakes.get(obj.constructor).get(id).deref();
|
||||||
|
snowflake.obj = obj;
|
||||||
|
return snowflake;
|
||||||
|
}
|
||||||
|
this.id = id;
|
||||||
|
SnowFlake.SnowFlakes.get(obj.constructor).set(id, new WeakRef(this));
|
||||||
|
SnowFlake.FinalizationRegistry.register(this, id);
|
||||||
|
this.obj = obj;
|
||||||
|
}
|
||||||
|
static getSnowFlakeFromID(id, type) {
|
||||||
|
if (!SnowFlake.SnowFlakes.get(type)) {
|
||||||
|
SnowFlake.SnowFlakes.set(type, new Map());
|
||||||
|
}
|
||||||
|
const snowflake = SnowFlake.SnowFlakes.get(type).get(id);
|
||||||
|
if (snowflake) {
|
||||||
|
return snowflake.deref();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const snowflake = new SnowFlake(id, undefined);
|
||||||
|
SnowFlake.SnowFlakes.get(type).set(id, new WeakRef(snowflake));
|
||||||
|
SnowFlake.FinalizationRegistry.register(snowflake, id);
|
||||||
|
return snowflake;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getUnixTime() {
|
||||||
|
return Number((BigInt(this.id) >> 22n) + 1420070400000n);
|
||||||
|
}
|
||||||
|
toString() {
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
getObject() {
|
||||||
|
return this.obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export { SnowFlake };
|
|
@ -1,7 +1,8 @@
|
||||||
//const usercache={};
|
//const usercache={};
|
||||||
import { Member } from "./member.js";
|
import { Member } from "./member.js";
|
||||||
import { markdown } from "./markdown.js";
|
import { MarkDown } from "./markdown.js";
|
||||||
import { Contextmenu } from "./contextmenu.js";
|
import { Contextmenu } from "./contextmenu.js";
|
||||||
|
import { SnowFlake } from "./snowflake.js";
|
||||||
class User {
|
class User {
|
||||||
static userids = {};
|
static userids = {};
|
||||||
owner;
|
owner;
|
||||||
|
@ -16,12 +17,12 @@ class User {
|
||||||
static contextmenu = new Contextmenu("User Menu");
|
static contextmenu = new Contextmenu("User Menu");
|
||||||
static setUpContextMenu() {
|
static setUpContextMenu() {
|
||||||
this.contextmenu.addbutton("Copy user id", function () {
|
this.contextmenu.addbutton("Copy user id", function () {
|
||||||
navigator.clipboard.writeText(this.id);
|
navigator.clipboard.writeText(this.id.id);
|
||||||
});
|
});
|
||||||
this.contextmenu.addbutton("Message user", function () {
|
this.contextmenu.addbutton("Message user", function () {
|
||||||
fetch(this.info.api.toString() + "/v9/users/@me/channels", { method: "POST",
|
fetch(this.info.api.toString() + "/v9/users/@me/channels", { method: "POST",
|
||||||
body: JSON.stringify({ "recipients": [this.id] }),
|
body: JSON.stringify({ "recipients": [this.id.id] }),
|
||||||
headers: this.headers
|
headers: this.localuser.headers
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -48,6 +49,14 @@ class User {
|
||||||
}
|
}
|
||||||
if (dontclone) {
|
if (dontclone) {
|
||||||
for (const thing of Object.keys(userjson)) {
|
for (const thing of Object.keys(userjson)) {
|
||||||
|
if (thing === "bio") {
|
||||||
|
this.bio = new MarkDown(userjson[thing], this.localuser);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (thing === "id") {
|
||||||
|
this.id = new SnowFlake(userjson[thing], this);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
this[thing] = userjson[thing];
|
this[thing] = userjson[thing];
|
||||||
}
|
}
|
||||||
this.hypotheticalpfp = false;
|
this.hypotheticalpfp = false;
|
||||||
|
@ -63,7 +72,7 @@ class User {
|
||||||
const pfp = document.createElement('img');
|
const pfp = document.createElement('img');
|
||||||
pfp.src = this.getpfpsrc();
|
pfp.src = this.getpfpsrc();
|
||||||
pfp.classList.add("pfp");
|
pfp.classList.add("pfp");
|
||||||
pfp.classList.add("userid:" + this.id);
|
pfp.classList.add("userid:" + this.id.id);
|
||||||
return pfp;
|
return pfp;
|
||||||
}
|
}
|
||||||
userupdate(json) {
|
userupdate(json) {
|
||||||
|
@ -73,7 +82,7 @@ class User {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bind(html, guild = null) {
|
bind(html, guild = null) {
|
||||||
if (guild && guild.id !== "@me") {
|
if (guild && guild.id.id !== "@me") {
|
||||||
Member.resolve(this, guild).then(_ => {
|
Member.resolve(this, guild).then(_ => {
|
||||||
_.bind(html);
|
_.bind(html);
|
||||||
}).catch(_ => {
|
}).catch(_ => {
|
||||||
|
@ -92,7 +101,7 @@ class User {
|
||||||
this.hypotheticalpfp = false;
|
this.hypotheticalpfp = false;
|
||||||
const src = this.getpfpsrc();
|
const src = this.getpfpsrc();
|
||||||
console.log(src);
|
console.log(src);
|
||||||
for (const thing of document.getElementsByClassName("userid:" + this.id)) {
|
for (const thing of document.getElementsByClassName("userid:" + this.id.id)) {
|
||||||
thing.src = src;
|
thing.src = src;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,7 +110,7 @@ class User {
|
||||||
return this.avatar;
|
return this.avatar;
|
||||||
}
|
}
|
||||||
if (this.avatar != null) {
|
if (this.avatar != null) {
|
||||||
return this.info.cdn.toString() + "avatars/" + this.id + "/" + this.avatar + ".png";
|
return this.info.cdn.toString() + "avatars/" + this.id.id + "/" + this.avatar + ".png";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return this.info.cdn.toString() + "embed/avatars/3.png";
|
return this.info.cdn.toString() + "embed/avatars/3.png";
|
||||||
|
@ -146,7 +155,7 @@ class User {
|
||||||
userbody.appendChild(pronounshtml);
|
userbody.appendChild(pronounshtml);
|
||||||
const rule = document.createElement("hr");
|
const rule = document.createElement("hr");
|
||||||
userbody.appendChild(rule);
|
userbody.appendChild(rule);
|
||||||
const biohtml = markdown(this.bio);
|
const biohtml = this.bio.makeHTML();
|
||||||
userbody.appendChild(biohtml);
|
userbody.appendChild(biohtml);
|
||||||
}
|
}
|
||||||
console.log(div);
|
console.log(div);
|
||||||
|
|
|
@ -3,14 +3,14 @@ import { Message } from "./message.js";
|
||||||
import {Voice} from "./audio.js";
|
import {Voice} from "./audio.js";
|
||||||
import {Contextmenu} from "./contextmenu.js";
|
import {Contextmenu} from "./contextmenu.js";
|
||||||
import {Fullscreen} from "./fullscreen.js";
|
import {Fullscreen} from "./fullscreen.js";
|
||||||
import {markdown} from "./markdown.js";
|
|
||||||
import {Guild} from "./guild.js";
|
import {Guild} from "./guild.js";
|
||||||
import { Localuser } from "./localuser.js";
|
import { Localuser } from "./localuser.js";
|
||||||
import { Permissions } from "./permissions.js";
|
import { Permissions } from "./permissions.js";
|
||||||
import { Settings, RoleList } from "./settings.js";
|
import { Settings, RoleList } from "./settings.js";
|
||||||
import { Role } from "./role.js";
|
import { Role } from "./role.js";
|
||||||
import {InfiniteScroller} from "./infiniteScroller.js"
|
import {InfiniteScroller} from "./infiniteScroller.js";
|
||||||
Settings;
|
import { SnowFlake } from "./snowflake.js";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface NotificationOptions {
|
interface NotificationOptions {
|
||||||
image?: string
|
image?: string
|
||||||
|
@ -22,30 +22,30 @@ class Channel{
|
||||||
owner:Guild;
|
owner:Guild;
|
||||||
headers:Localuser["headers"];
|
headers:Localuser["headers"];
|
||||||
name:string;
|
name:string;
|
||||||
id:string;
|
id:SnowFlake<Channel>;
|
||||||
parent_id:string;
|
parent_id:SnowFlake<Channel>;
|
||||||
parent:Channel;
|
parent:Channel;
|
||||||
children:Channel[];
|
children:Channel[];
|
||||||
guild_id:string;
|
guild_id:string;
|
||||||
messageids:{[key : string]:Message};
|
messageids:Map<SnowFlake<Message>,Message>;
|
||||||
permission_overwrites:{[key:string]:Permissions};
|
permission_overwrites:Map<string,Permissions>;
|
||||||
permission_overwritesar:[string,Permissions][]
|
permission_overwritesar:[SnowFlake<Role>,Permissions][]
|
||||||
topic:string;
|
topic:string;
|
||||||
nsfw:boolean;
|
nsfw:boolean;
|
||||||
position:number;
|
position:number;
|
||||||
lastreadmessageid:string;
|
lastreadmessageid:SnowFlake<Message>;
|
||||||
lastmessageid:string;
|
lastmessageid:SnowFlake<Message>;
|
||||||
mentions:number;
|
mentions:number;
|
||||||
lastpin:string;
|
lastpin:string;
|
||||||
move_id:string;
|
move_id:SnowFlake<Channel>;
|
||||||
typing:number;
|
typing:number;
|
||||||
message_notifications:number;
|
message_notifications:number;
|
||||||
allthewayup:boolean;
|
allthewayup:boolean;
|
||||||
static contextmenu=new Contextmenu("channel menu");
|
static contextmenu=new Contextmenu("channel menu");
|
||||||
replyingto:Message;
|
replyingto:Message;
|
||||||
infinite:InfiniteScroller;
|
infinite:InfiniteScroller;
|
||||||
idToPrev:{[key:string]:string}={};
|
idToPrev:Map<SnowFlake<Message>,SnowFlake<Message>>=new Map();
|
||||||
idToNext:{[key:string]:string}={};
|
idToNext:Map<SnowFlake<Message>,SnowFlake<Message>>=new Map();
|
||||||
static setupcontextmenu(){
|
static setupcontextmenu(){
|
||||||
this.contextmenu.addbutton("Copy channel id",function(){
|
this.contextmenu.addbutton("Copy channel id",function(){
|
||||||
console.log(this)
|
console.log(this)
|
||||||
|
@ -87,26 +87,28 @@ class Channel{
|
||||||
}
|
}
|
||||||
setUpInfiniteScroller(){
|
setUpInfiniteScroller(){
|
||||||
const ids:{[key:string]:Function}={};
|
const ids:{[key:string]:Function}={};
|
||||||
this.infinite=new InfiniteScroller(async function(id:string,offset:number){
|
this.infinite=new InfiniteScroller(async function(this:Channel,id:string,offset:number):Promise<string>{
|
||||||
|
const snowflake=SnowFlake.getSnowFlakeFromID(id,Message) as SnowFlake<Message>;
|
||||||
if(offset===1){
|
if(offset===1){
|
||||||
if(this.idToPrev[id]){
|
if(this.idToPrev.get(snowflake)){
|
||||||
return this.idToPrev[id];
|
return this.idToPrev.get(snowflake)?.id;
|
||||||
}else{
|
}else{
|
||||||
await this.grabmoremessages(id);
|
await this.grabBefore(id);
|
||||||
return this.idToPrev[id];
|
return this.idToPrev.get(snowflake)?.id;
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
return this.idToNext[id];
|
return this.idToNext.get(snowflake)?.id;
|
||||||
}
|
}
|
||||||
}.bind(this),
|
}.bind(this),
|
||||||
function(this:Channel,id:string){
|
function(this:Channel,id:string){
|
||||||
let res:Function;
|
let res:Function;
|
||||||
const promise=new Promise(_=>{res=_;}) as Promise<void>;
|
const promise=new Promise(_=>{res=_;}) as Promise<void>;
|
||||||
const html=this.messageids[id].buildhtml(this.messageids[this.idToPrev[id]],promise);
|
const snowflake=SnowFlake.getSnowFlakeFromID(id,Message) as SnowFlake<Message>;
|
||||||
|
const html=this.messageids.get(snowflake).buildhtml(this.messageids.get(this.idToPrev.get(snowflake)),promise);
|
||||||
ids[id]=res;
|
ids[id]=res;
|
||||||
return html;
|
return html;
|
||||||
}.bind(this),
|
}.bind(this),
|
||||||
async function(id:string){
|
async function(this:Channel,id:string){
|
||||||
ids[id]();
|
ids[id]();
|
||||||
delete ids[id];
|
delete ids[id];
|
||||||
return true;
|
return true;
|
||||||
|
@ -125,26 +127,25 @@ class Channel{
|
||||||
this.owner=owner;
|
this.owner=owner;
|
||||||
this.headers=this.owner.headers;
|
this.headers=this.owner.headers;
|
||||||
this.name=JSON.name;
|
this.name=JSON.name;
|
||||||
this.id=JSON.id;
|
this.id=new SnowFlake(JSON.id,this);
|
||||||
this.parent_id=JSON.parent_id;
|
this.parent_id=new SnowFlake(JSON.parent_id,undefined);
|
||||||
this.parent=null;
|
this.parent=null;
|
||||||
this.children=[];
|
this.children=[];
|
||||||
this.guild_id=JSON.guild_id;
|
this.guild_id=JSON.guild_id;
|
||||||
this.messageids={};
|
this.messageids=new Map();
|
||||||
this.permission_overwrites={};
|
this.permission_overwrites=new Map();
|
||||||
this.permission_overwritesar=[];
|
this.permission_overwritesar=[];
|
||||||
for(const thing of JSON.permission_overwrites){
|
for(const thing of JSON.permission_overwrites){
|
||||||
console.log(thing);
|
|
||||||
if(thing.id==="1182819038095799904"||thing.id==="1182820803700625444"){continue;};
|
if(thing.id==="1182819038095799904"||thing.id==="1182820803700625444"){continue;};
|
||||||
this.permission_overwrites[thing.id]=new Permissions(thing.allow,thing.deny);
|
this.permission_overwrites.set(thing.id,new Permissions(thing.allow,thing.deny));
|
||||||
this.permission_overwritesar.push([thing.id,this.permission_overwrites[thing.id]]);
|
this.permission_overwritesar.push([thing.id,this.permission_overwrites.get(thing.id)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.topic=JSON.topic;
|
this.topic=JSON.topic;
|
||||||
this.nsfw=JSON.nsfw;
|
this.nsfw=JSON.nsfw;
|
||||||
this.position=JSON.position;
|
this.position=JSON.position;
|
||||||
this.lastreadmessageid=null;
|
this.lastreadmessageid=null;
|
||||||
this.lastmessageid=JSON.last_message_id;
|
this.lastmessageid=SnowFlake.getSnowFlakeFromID(JSON.last_message_id,Message);
|
||||||
this.setUpInfiniteScroller();
|
this.setUpInfiniteScroller();
|
||||||
}
|
}
|
||||||
isAdmin(){
|
isAdmin(){
|
||||||
|
@ -160,22 +161,22 @@ class Channel{
|
||||||
return this.owner.info;
|
return this.owner.info;
|
||||||
}
|
}
|
||||||
readStateInfo(json){
|
readStateInfo(json){
|
||||||
this.lastreadmessageid=json.last_message_id;
|
this.lastreadmessageid=SnowFlake.getSnowFlakeFromID(json.last_message_id,Message);
|
||||||
this.mentions=json.mention_count;
|
this.mentions=json.mention_count;
|
||||||
this.mentions??=0;
|
this.mentions??=0;
|
||||||
this.lastpin=json.last_pin_timestamp;
|
this.lastpin=json.last_pin_timestamp;
|
||||||
}
|
}
|
||||||
get hasunreads():boolean{
|
get hasunreads():boolean{
|
||||||
if(!this.hasPermission("VIEW_CHANNEL")){return false;}
|
if(!this.hasPermission("VIEW_CHANNEL")){return false;}
|
||||||
return this.lastmessageid!==this.lastreadmessageid&&this.type!==4;
|
return this.lastmessageid!==this.lastreadmessageid&&this.type!==4&&!!this.lastmessageid.id;
|
||||||
}
|
}
|
||||||
hasPermission(name:string,member=this.guild.member):boolean{
|
hasPermission(name:string,member=this.guild.member):boolean{
|
||||||
if(member.isAdmin()){
|
if(member.isAdmin()){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
for(const thing of member.roles){
|
for(const thing of member.roles){
|
||||||
if(this.permission_overwrites[thing.id]){
|
if(this.permission_overwrites.get(thing.id.id)){
|
||||||
let perm=this.permission_overwrites[thing.id].getPermission(name);
|
let perm=this.permission_overwrites.get(thing.id.id).getPermission(name);
|
||||||
if(perm){
|
if(perm){
|
||||||
return perm===1;
|
return perm===1;
|
||||||
}
|
}
|
||||||
|
@ -196,7 +197,7 @@ class Channel{
|
||||||
this.children.sort((a,b)=>{return a.position-b.position});
|
this.children.sort((a,b)=>{return a.position-b.position});
|
||||||
}
|
}
|
||||||
resolveparent(guild:Guild){
|
resolveparent(guild:Guild){
|
||||||
this.parent=guild.channelids[this.parent_id];
|
this.parent=guild.channelids[this.parent_id?.id];
|
||||||
this.parent??=null;
|
this.parent??=null;
|
||||||
if(this.parent!==null){
|
if(this.parent!==null){
|
||||||
this.parent.children.push(this);
|
this.parent.children.push(this);
|
||||||
|
@ -354,7 +355,7 @@ class Channel{
|
||||||
if(!this.hasunreads){
|
if(!this.hasunreads){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fetch(this.info.api.toString()+"/v9/channels/"+this.id+"/messages/"+this.lastmessageid+"/ack",{
|
fetch(this.info.api.toString()+"/channels/"+this.id+"/messages/"+this.lastmessageid+"/ack",{
|
||||||
method:"POST",
|
method:"POST",
|
||||||
headers:this.headers,
|
headers:this.headers,
|
||||||
body:JSON.stringify({})
|
body:JSON.stringify({})
|
||||||
|
@ -445,8 +446,8 @@ class Channel{
|
||||||
["textbox","Channel name:",this.name,function(){name=this.value}],
|
["textbox","Channel name:",this.name,function(){name=this.value}],
|
||||||
["mdbox","Channel topic:",this.topic,function(){topic=this.value}],
|
["mdbox","Channel topic:",this.topic,function(){topic=this.value}],
|
||||||
["checkbox","NSFW Channel",this.nsfw,function(){nsfw=this.checked}],
|
["checkbox","NSFW Channel",this.nsfw,function(){nsfw=this.checked}],
|
||||||
["button","","submit",function(){
|
["button","","submit",()=>{
|
||||||
fetch(this.info.api.toString()+"/v9/channels/"+thisid,{
|
fetch(this.info.api.toString()+"/channels/"+thisid,{
|
||||||
method:"PATCH",
|
method:"PATCH",
|
||||||
headers:this.headers,
|
headers:this.headers,
|
||||||
body:JSON.stringify({
|
body:JSON.stringify({
|
||||||
|
@ -470,7 +471,7 @@ class Channel{
|
||||||
console.log(full)
|
console.log(full)
|
||||||
}
|
}
|
||||||
deleteChannel(){
|
deleteChannel(){
|
||||||
fetch(this.info.api.toString()+"/v9/channels/"+this.id,{
|
fetch(this.info.api.toString()+"/channels/"+this.id,{
|
||||||
method:"DELETE",
|
method:"DELETE",
|
||||||
headers:this.headers
|
headers:this.headers
|
||||||
})
|
})
|
||||||
|
@ -508,10 +509,11 @@ class Channel{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async getmessage(id:string):Promise<Message>{
|
async getmessage(id:string):Promise<Message>{
|
||||||
if(this.messageids[id]){
|
const snowflake=SnowFlake.getSnowFlakeFromID(id,Message) as SnowFlake<Message>;
|
||||||
return this.messageids[id];
|
if(snowflake.getObject()){
|
||||||
|
return snowflake.getObject();
|
||||||
}else{
|
}else{
|
||||||
const gety=await fetch(this.info.api.toString()+"/v9/channels/"+this.id+"/messages?limit=1&around="+id,{headers:this.headers})
|
const gety=await fetch(this.info.api.toString()+"/channels/"+this.id+"/messages?limit=1&around="+id,{headers:this.headers})
|
||||||
const json=await gety.json();
|
const json=await gety.json();
|
||||||
return new Message(json[0],this);
|
return new Message(json[0],this);
|
||||||
}
|
}
|
||||||
|
@ -539,13 +541,15 @@ class Channel{
|
||||||
history.pushState(null, null,"/channels/"+this.guild_id+"/"+this.id);
|
history.pushState(null, null,"/channels/"+this.guild_id+"/"+this.id);
|
||||||
document.getElementById("channelname").textContent="#"+this.name;
|
document.getElementById("channelname").textContent="#"+this.name;
|
||||||
console.log(this);
|
console.log(this);
|
||||||
(document.getElementById("typebox") as HTMLInputElement).disabled=!this.canMessage;
|
(document.getElementById("typebox") as HTMLInputElement).contentEditable=""+this.canMessage;
|
||||||
}
|
}
|
||||||
|
lastmessage:Message;
|
||||||
async putmessages(){
|
async putmessages(){
|
||||||
if(this.allthewayup){return};
|
if(this.allthewayup){return};
|
||||||
const j=await fetch(this.info.api.toString()+"/channels/"+this.id+"/messages?limit=100",{
|
const j=await fetch(this.info.api.toString()+"/channels/"+this.id+"/messages?limit=100",{
|
||||||
headers: this.headers,
|
headers: this.headers,
|
||||||
})
|
});
|
||||||
|
|
||||||
const response=await j.json();
|
const response=await j.json();
|
||||||
if(response.length!==100){
|
if(response.length!==100){
|
||||||
this.allthewayup=true;
|
this.allthewayup=true;
|
||||||
|
@ -554,12 +558,14 @@ class Channel{
|
||||||
for(const thing of response){
|
for(const thing of response){
|
||||||
const message=new Message(thing,this);
|
const message=new Message(thing,this);
|
||||||
if(prev){
|
if(prev){
|
||||||
this.idToNext[message.id]=prev.id;
|
this.idToNext.set(message.id,prev.id);
|
||||||
this.idToPrev[prev.id]=message.id;
|
this.idToPrev.set(prev.id,message.id);
|
||||||
|
}else{
|
||||||
|
this.lastmessage=message;
|
||||||
}
|
}
|
||||||
prev=message;
|
prev=message;
|
||||||
if(this.messageids[message.id]===undefined){
|
if(this.messageids.get(message.id)===undefined){
|
||||||
this.messageids[message.id]=message;
|
this.messageids.set(message.id,message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -572,7 +578,7 @@ class Channel{
|
||||||
}
|
}
|
||||||
this.children=build;
|
this.children=build;
|
||||||
}
|
}
|
||||||
async grabmoremessages(id:string){
|
async grabBefore(id:string){
|
||||||
if(this.allthewayup){
|
if(this.allthewayup){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -584,7 +590,7 @@ class Channel{
|
||||||
if(response.length===0){
|
if(response.length===0){
|
||||||
this.allthewayup=true;
|
this.allthewayup=true;
|
||||||
}
|
}
|
||||||
let previd=id;
|
let previd=SnowFlake.getSnowFlakeFromID(id,Message) as SnowFlake<Message>;
|
||||||
for(const i in response){
|
for(const i in response){
|
||||||
let messager:Message;
|
let messager:Message;
|
||||||
if(!next){
|
if(!next){
|
||||||
|
@ -598,11 +604,11 @@ class Channel{
|
||||||
next=undefined;
|
next=undefined;
|
||||||
console.log("ohno",+i+1);
|
console.log("ohno",+i+1);
|
||||||
}
|
}
|
||||||
if(this.messageids[messager.id]===undefined){
|
if(this.messageids.get(messager.id)===undefined){
|
||||||
this.idToNext[messager.id]=previd;
|
this.idToNext.set(messager.id,previd);
|
||||||
this.idToPrev[previd]=messager.id;
|
this.idToPrev.set(previd,messager.id);
|
||||||
previd=messager.id;
|
previd=messager.id;
|
||||||
this.messageids[messager.id]=messager;
|
this.messageids.set(messager.id,messager);
|
||||||
}else{
|
}else{
|
||||||
console.log("How???")
|
console.log("How???")
|
||||||
}
|
}
|
||||||
|
@ -618,17 +624,42 @@ class Channel{
|
||||||
buildmessages(){
|
buildmessages(){
|
||||||
const messages=document.getElementById("channelw");
|
const messages=document.getElementById("channelw");
|
||||||
messages.innerHTML="";
|
messages.innerHTML="";
|
||||||
messages.append(this.infinite.getDiv(this.lastmessageid));
|
let id:SnowFlake<Message>;
|
||||||
|
if(this.messageids.get(this.lastreadmessageid)){
|
||||||
|
id=this.lastreadmessageid;
|
||||||
|
}else if(this.lastmessage.id){
|
||||||
|
id=this.goBackIds(this.lastmessage.id,50);
|
||||||
|
console.log("shouldn't")
|
||||||
|
}
|
||||||
|
messages.append(this.infinite.getDiv(id.id));
|
||||||
|
}
|
||||||
|
private goBackIds(id:SnowFlake<Message>,back:number):SnowFlake<Message>{
|
||||||
|
while(back!==0){
|
||||||
|
const nextid=this.idToPrev.get(id);
|
||||||
|
if(nextid){
|
||||||
|
id=nextid;
|
||||||
|
console.log(id);
|
||||||
|
back--;
|
||||||
|
}else{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return id;
|
||||||
}
|
}
|
||||||
updateChannel(JSON){
|
updateChannel(JSON){
|
||||||
this.type=JSON.type;
|
this.type=JSON.type;
|
||||||
this.name=JSON.name;
|
this.name=JSON.name;
|
||||||
this.parent_id=JSON.parent_id;
|
this.parent_id=new SnowFlake(JSON.parent_id,undefined);
|
||||||
this.parent=null;
|
this.parent=null;
|
||||||
this.children=[];
|
this.children=[];
|
||||||
this.guild_id=JSON.guild_id;
|
this.guild_id=JSON.guild_id;
|
||||||
this.messageids={};
|
this.messageids=new Map();
|
||||||
this.permission_overwrites=JSON.permission_overwrites;
|
this.permission_overwrites=new Map();
|
||||||
|
for(const thing of JSON.permission_overwrites){
|
||||||
|
if(thing.id==="1182819038095799904"||thing.id==="1182820803700625444"){continue;};
|
||||||
|
this.permission_overwrites.set(thing.id,new Permissions(thing.allow,thing.deny));
|
||||||
|
this.permission_overwritesar.push([thing.id,this.permission_overwrites.get(thing.id)]);
|
||||||
|
}
|
||||||
this.topic=JSON.topic;
|
this.topic=JSON.topic;
|
||||||
this.nsfw=JSON.nsfw;
|
this.nsfw=JSON.nsfw;
|
||||||
}
|
}
|
||||||
|
@ -662,9 +693,9 @@ class Channel{
|
||||||
if(replyingto){
|
if(replyingto){
|
||||||
replyjson=
|
replyjson=
|
||||||
{
|
{
|
||||||
"guild_id":replyingto.guild.id,
|
"guild_id":replyingto.guild.id.id,
|
||||||
"channel_id": replyingto.channel.id,
|
"channel_id": replyingto.channel.id.id,
|
||||||
"message_id": replyingto.id,
|
"message_id": replyingto.id.id,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
if(attachments.length===0){
|
if(attachments.length===0){
|
||||||
|
@ -707,10 +738,11 @@ class Channel{
|
||||||
messageCreate(messagep:any):void{
|
messageCreate(messagep:any):void{
|
||||||
if(!this.hasPermission("VIEW_CHANNEL")){return}
|
if(!this.hasPermission("VIEW_CHANNEL")){return}
|
||||||
const messagez=new Message(messagep.d,this);
|
const messagez=new Message(messagep.d,this);
|
||||||
this.idToNext[this.lastmessageid]=messagez.id;
|
console.log(this.lastmessageid,messagez.id,":3");
|
||||||
this.idToPrev[messagez.id]=this.lastmessageid;
|
this.idToNext.set(this.lastmessageid,messagez.id);
|
||||||
|
this.idToPrev.set(messagez.id,this.lastmessageid);
|
||||||
this.lastmessageid=messagez.id;
|
this.lastmessageid=messagez.id;
|
||||||
this.messageids[messagez.id]=messagez;
|
this.messageids.set(messagez.id,messagez);
|
||||||
if(messagez.author===this.localuser.user){
|
if(messagez.author===this.localuser.user){
|
||||||
this.lastreadmessageid=messagez.id;
|
this.lastreadmessageid=messagez.id;
|
||||||
if(this.myhtml){
|
if(this.myhtml){
|
||||||
|
@ -744,10 +776,10 @@ class Channel{
|
||||||
if (!("Notification" in window)) {
|
if (!("Notification" in window)) {
|
||||||
|
|
||||||
} else if (Notification.permission === "granted") {
|
} else if (Notification.permission === "granted") {
|
||||||
let noticontent=markdown(message.content).textContent;
|
let noticontent=message.content.textContent;
|
||||||
if(message.embeds[0]){
|
if(message.embeds[0]){
|
||||||
noticontent||=message.embeds[0].json.title;
|
noticontent||=message.embeds[0].json.title;
|
||||||
noticontent||=markdown(message.embeds[0].json.description).textContent;
|
noticontent||=message.content.textContent;
|
||||||
}
|
}
|
||||||
noticontent||="Blank Message";
|
noticontent||="Blank Message";
|
||||||
let imgurl=null;
|
let imgurl=null;
|
||||||
|
@ -785,11 +817,11 @@ class Channel{
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
const perm=new Permissions("0","0");
|
const perm=new Permissions("0","0");
|
||||||
this.permission_overwrites[role.id]=perm;
|
this.permission_overwrites.set(role.id.id,perm);
|
||||||
this.permission_overwritesar.push([role.id,perm]);
|
this.permission_overwritesar.push([role.id,perm]);
|
||||||
}
|
}
|
||||||
async updateRolePermissions(id:string,perms:Permissions){
|
async updateRolePermissions(id:string,perms:Permissions){
|
||||||
const permission=this.permission_overwrites[id];
|
const permission=this.permission_overwrites.get(id);
|
||||||
permission.allow=perms.allow;
|
permission.allow=perms.allow;
|
||||||
permission.deny=perms.deny;
|
permission.deny=perms.deny;
|
||||||
await fetch(this.info.api.toString()+"/channels/"+this.id+"/permissions/"+id,{
|
await fetch(this.info.api.toString()+"/channels/"+this.id+"/permissions/"+id,{
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { Message } from "./message.js";
|
||||||
import { Localuser } from "./localuser.js";
|
import { Localuser } from "./localuser.js";
|
||||||
import {User} from "./user.js";
|
import {User} from "./user.js";
|
||||||
import { Member } from "./member.js";
|
import { Member } from "./member.js";
|
||||||
|
import { SnowFlake } from "./snowflake.js";
|
||||||
|
|
||||||
class Direct extends Guild{
|
class Direct extends Guild{
|
||||||
constructor(JSON,owner:Localuser){
|
constructor(JSON,owner:Localuser){
|
||||||
|
@ -17,16 +18,16 @@ class Direct extends Guild{
|
||||||
this.headers=this.localuser.headers;
|
this.headers=this.localuser.headers;
|
||||||
this.channels=[];
|
this.channels=[];
|
||||||
this.channelids={};
|
this.channelids={};
|
||||||
this.id="@me";
|
this.id=new SnowFlake("@me",this);
|
||||||
this.properties={};
|
this.properties={};
|
||||||
this.roles=[];
|
this.roles=[];
|
||||||
this.roleids={};
|
this.roleids=new Map();
|
||||||
this.prevchannel=undefined;
|
this.prevchannel=undefined;
|
||||||
this.properties.name="Direct Messages";
|
this.properties.name="Direct Messages";
|
||||||
for(const thing of JSON){
|
for(const thing of JSON){
|
||||||
const temp=new Group(thing,this);
|
const temp=new Group(thing,this);
|
||||||
this.channels.push(temp);
|
this.channels.push(temp);
|
||||||
this.channelids[temp.id]=temp;
|
this.channelids[temp.id.id]=temp;
|
||||||
}
|
}
|
||||||
this.headchannels=this.channels;
|
this.headchannels=this.channels;
|
||||||
}
|
}
|
||||||
|
@ -39,7 +40,7 @@ class Direct extends Guild{
|
||||||
}
|
}
|
||||||
sortchannels(){
|
sortchannels(){
|
||||||
this.headchannels.sort((a,b)=>{
|
this.headchannels.sort((a,b)=>{
|
||||||
const result=(BigInt(a.lastmessageid)-BigInt(b.lastmessageid));
|
const result=(a.lastmessageid.getUnixTime()-b.lastmessageid.getUnixTime());
|
||||||
return Number(-result);
|
return Number(-result);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -74,15 +75,15 @@ class Group extends Channel{
|
||||||
this.user=this.localuser.user;
|
this.user=this.localuser.user;
|
||||||
}
|
}
|
||||||
this.name??=this.localuser.user.username;
|
this.name??=this.localuser.user.username;
|
||||||
this.id=JSON.id;
|
this.id=new SnowFlake(JSON.id,this);
|
||||||
this.parent_id=null;
|
this.parent_id=null;
|
||||||
this.parent=null;
|
this.parent=null;
|
||||||
this.children=[];
|
this.children=[];
|
||||||
this.guild_id="@me";
|
this.guild_id="@me";
|
||||||
this.messageids={};
|
this.messageids=new Map();
|
||||||
this.permission_overwrites={};
|
this.permission_overwrites=new Map();
|
||||||
this.lastmessageid=JSON.last_message_id;
|
this.lastmessageid=SnowFlake.getSnowFlakeFromID(JSON.last_message_id,Message);
|
||||||
this.lastmessageid??="0";
|
this.lastmessageid??=new SnowFlake("0",undefined);
|
||||||
this.mentions=0;
|
this.mentions=0;
|
||||||
this.setUpInfiniteScroller();
|
this.setUpInfiniteScroller();
|
||||||
}
|
}
|
||||||
|
@ -118,10 +119,10 @@ class Group extends Channel{
|
||||||
}
|
}
|
||||||
messageCreate(messagep){
|
messageCreate(messagep){
|
||||||
const messagez=new Message(messagep.d,this);
|
const messagez=new Message(messagep.d,this);
|
||||||
this.idToNext[this.lastmessageid]=messagez.id;
|
this.idToNext.set(this.lastmessageid,messagez.id);
|
||||||
this.idToPrev[messagez.id]=this.lastmessageid;
|
this.idToPrev.set(messagez.id,this.lastmessageid);
|
||||||
this.lastmessageid=messagez.id;
|
this.lastmessageid=messagez.id;
|
||||||
this.messageids[messagez.id]=messagez;
|
this.messageids.set(messagez.id,messagez);
|
||||||
if(messagez.author===this.localuser.user){
|
if(messagez.author===this.localuser.user){
|
||||||
this.lastreadmessageid=messagez.id;
|
this.lastreadmessageid=messagez.id;
|
||||||
if(this.myhtml){
|
if(this.myhtml){
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import {Fullscreen} from "./fullscreen.js";
|
import {Fullscreen} from "./fullscreen.js";
|
||||||
import {Message} from "./message.js";
|
import {Message} from "./message.js";
|
||||||
import {markdown} from "./markdown.js";
|
import {MarkDown} from "./markdown.js";
|
||||||
|
|
||||||
class Embed{
|
class Embed{
|
||||||
type:string;
|
type:string;
|
||||||
|
@ -29,6 +29,18 @@ class Embed{
|
||||||
return document.createElement("div");//prevent errors by giving blank div
|
return document.createElement("div");//prevent errors by giving blank div
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
get message(){
|
||||||
|
return this.owner;
|
||||||
|
}
|
||||||
|
get channel(){
|
||||||
|
return this.message.channel;
|
||||||
|
}
|
||||||
|
get guild(){
|
||||||
|
return this.channel.guild;
|
||||||
|
}
|
||||||
|
get localuser(){
|
||||||
|
return this.guild.localuser;
|
||||||
|
}
|
||||||
generateRich(){
|
generateRich(){
|
||||||
console.log(this.json)
|
console.log(this.json)
|
||||||
const div=document.createElement("div");
|
const div=document.createElement("div");
|
||||||
|
@ -59,7 +71,7 @@ class Embed{
|
||||||
embed.append(authorline);
|
embed.append(authorline);
|
||||||
}
|
}
|
||||||
const title=document.createElement("a");
|
const title=document.createElement("a");
|
||||||
title.append(markdown(this.json.title));
|
title.append(new MarkDown(this.json.title,this.channel).makeHTML());
|
||||||
if(this.json.url){
|
if(this.json.url){
|
||||||
title.href=this.json.url;
|
title.href=this.json.url;
|
||||||
}
|
}
|
||||||
|
@ -68,7 +80,7 @@ class Embed{
|
||||||
|
|
||||||
if(this.json.description){
|
if(this.json.description){
|
||||||
const p=document.createElement("p");
|
const p=document.createElement("p");
|
||||||
p.append(markdown(this.json.description));
|
p.append(new MarkDown(this.json.description,this.channel).makeHTML());
|
||||||
embed.append(p);
|
embed.append(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +92,7 @@ class Embed{
|
||||||
b.textContent=thing.name;
|
b.textContent=thing.name;
|
||||||
div.append(b);
|
div.append(b);
|
||||||
const p=document.createElement("p")
|
const p=document.createElement("p")
|
||||||
p.append(markdown(thing.value));
|
p.append(new MarkDown(thing.value,this.channel).makeHTML());
|
||||||
p.classList.add("embedp");
|
p.classList.add("embedp");
|
||||||
div.append(p);
|
div.append(p);
|
||||||
|
|
||||||
|
|
|
@ -6,15 +6,16 @@ import {Fullscreen} from "./fullscreen.js";
|
||||||
import {Member} from "./member.js";
|
import {Member} from "./member.js";
|
||||||
import {Settings,RoleList} from "./settings.js";
|
import {Settings,RoleList} from "./settings.js";
|
||||||
import {Permissions} from "./permissions.js";
|
import {Permissions} from "./permissions.js";
|
||||||
|
import { SnowFlake } from "./snowflake.js";
|
||||||
class Guild{
|
class Guild{
|
||||||
owner:Localuser;
|
owner:Localuser;
|
||||||
headers:Localuser["headers"];
|
headers:Localuser["headers"];
|
||||||
channels:Channel[];
|
channels:Channel[];
|
||||||
channelids:{[key:string]:Channel};
|
channelids:{[key:string]:Channel};
|
||||||
id:string;
|
id:SnowFlake<Guild>;
|
||||||
properties
|
properties
|
||||||
roles:Role[];
|
roles:Role[];
|
||||||
roleids:{[key:string]:Role};
|
roleids:Map<SnowFlake<Role>,Role>;
|
||||||
prevchannel:Channel;
|
prevchannel:Channel;
|
||||||
message_notifications:number;
|
message_notifications:number;
|
||||||
headchannels:Channel[];
|
headchannels:Channel[];
|
||||||
|
@ -75,30 +76,30 @@ class Guild{
|
||||||
s1.options.push(new RoleList(permlist,this,this.updateRolePermissions.bind(this)));
|
s1.options.push(new RoleList(permlist,this,this.updateRolePermissions.bind(this)));
|
||||||
settings.show();
|
settings.show();
|
||||||
}
|
}
|
||||||
constructor(JSON,owner:Localuser,member){
|
constructor(json,owner:Localuser,member){
|
||||||
if(JSON===-1){
|
if(json===-1){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.owner=owner;
|
this.owner=owner;
|
||||||
this.headers=this.owner.headers;
|
this.headers=this.owner.headers;
|
||||||
this.channels=[];
|
this.channels=[];
|
||||||
this.channelids={};
|
this.channelids={};
|
||||||
this.id=JSON.id;
|
this.id=new SnowFlake(json.id,this);
|
||||||
this.properties=JSON.properties;
|
this.properties=json.properties;
|
||||||
this.roles=[];
|
this.roles=[];
|
||||||
this.roleids={};
|
this.roleids=new Map();
|
||||||
this.prevchannel=undefined;
|
this.prevchannel=undefined;
|
||||||
this.message_notifications=0;
|
this.message_notifications=0;
|
||||||
for(const roley of JSON.roles){
|
for(const roley of json.roles){
|
||||||
const roleh=new Role(roley,this);
|
const roleh=new Role(roley,this);
|
||||||
this.roles.push(roleh)
|
this.roles.push(roleh)
|
||||||
this.roleids[roleh.id]=roleh;
|
this.roleids.set(roleh.id,roleh);
|
||||||
}
|
}
|
||||||
Member.resolve(member,this).then(_=>this.member=_);
|
Member.resolve(member,this).then(_=>this.member=_);
|
||||||
for(const thing of JSON.channels){
|
for(const thing of json.channels){
|
||||||
const temp=new Channel(thing,this);
|
const temp=new Channel(thing,this);
|
||||||
this.channels.push(temp);
|
this.channels.push(temp);
|
||||||
this.channelids[temp.id]=temp;
|
this.channelids[temp.id.id]=temp;
|
||||||
}
|
}
|
||||||
this.headchannels=[];
|
this.headchannels=[];
|
||||||
for(const thing of this.channels){
|
for(const thing of this.channels){
|
||||||
|
@ -128,7 +129,7 @@ class Guild{
|
||||||
headers:this.headers,
|
headers:this.headers,
|
||||||
body:JSON.stringify({
|
body:JSON.stringify({
|
||||||
"guilds":{
|
"guilds":{
|
||||||
[this.id]:{
|
[this.id.id]:{
|
||||||
"message_notifications": noti
|
"message_notifications": noti
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -247,7 +248,7 @@ class Guild{
|
||||||
const noti=document.createElement("div");
|
const noti=document.createElement("div");
|
||||||
noti.classList.add("unread");
|
noti.classList.add("unread");
|
||||||
divy.append(noti);
|
divy.append(noti);
|
||||||
this.localuser.guildhtml[this.id]=divy;
|
this.localuser.guildhtml[this.id.id]=divy;
|
||||||
if(this.properties.icon!=null){
|
if(this.properties.icon!=null){
|
||||||
const img=document.createElement("img");
|
const img=document.createElement("img");
|
||||||
img.classList.add("pfp","servericon");
|
img.classList.add("pfp","servericon");
|
||||||
|
@ -373,16 +374,12 @@ class Guild{
|
||||||
body:JSON.stringify(build)
|
body:JSON.stringify(build)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
getRole(ID:string):Role{
|
|
||||||
if(!this.roleids[ID]){console.error(`role id ${ID} does not exist`,this.roleids)}
|
|
||||||
return this.roleids[ID];
|
|
||||||
}
|
|
||||||
hasRole(r:Role|string){
|
hasRole(r:Role|string){
|
||||||
console.log("this should run");
|
console.log("this should run");
|
||||||
if((typeof r)!==(typeof "")){
|
if(r instanceof Role){
|
||||||
r=(r as Role).id;
|
r=r.id.id;
|
||||||
}
|
}
|
||||||
return this.member.hasRole(r as string);
|
return this.member.hasRole(r);
|
||||||
}
|
}
|
||||||
loadChannel(ID:string=undefined){
|
loadChannel(ID:string=undefined){
|
||||||
if(ID&&this.channelids[ID]){
|
if(ID&&this.channelids[ID]){
|
||||||
|
@ -402,10 +399,10 @@ class Guild{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
loadGuild(){
|
loadGuild(){
|
||||||
this.localuser.loadGuild(this.id);
|
this.localuser.loadGuild(this.id.id);
|
||||||
}
|
}
|
||||||
updateChannel(JSON){
|
updateChannel(JSON){
|
||||||
this.channelids[JSON.id].updateChannel(JSON);
|
SnowFlake.getSnowFlakeFromID(JSON.id,Channel).getObject().updateChannel(JSON);
|
||||||
this.headchannels=[];
|
this.headchannels=[];
|
||||||
for(const thing of this.channels){
|
for(const thing of this.channels){
|
||||||
thing.children=[];
|
thing.children=[];
|
||||||
|
@ -516,7 +513,7 @@ class Guild{
|
||||||
})
|
})
|
||||||
const json=await fetched.json();
|
const json=await fetched.json();
|
||||||
const role=new Role(json,this);
|
const role=new Role(json,this);
|
||||||
this.roleids[role.id]=role;
|
this.roleids[role.id.id]=role;
|
||||||
this.roles.push(role);
|
this.roles.push(role);
|
||||||
return role;
|
return role;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,12 @@
|
||||||
<p id="status">STATUS</p>
|
<p id="status">STATUS</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="user-actions">
|
||||||
<h2 id="settings">⚙</h2>
|
<h2 id="settings">⚙</h2>
|
||||||
|
<h2 id="connections">🔗</h2>
|
||||||
|
<h2 id="dev-portal">🤖</h2>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flexttb messageflex">
|
<div class="flexttb messageflex">
|
||||||
|
@ -53,7 +58,7 @@
|
||||||
<div id="pasteimage"></div>
|
<div id="pasteimage"></div>
|
||||||
<div id="replybox" class="hideReplyBox"></div>
|
<div id="replybox" class="hideReplyBox"></div>
|
||||||
<div id="typediv">
|
<div id="typediv">
|
||||||
<textarea id="typebox"></textarea>
|
<div id="typebox" contentEditable="true"></div>
|
||||||
<div id="typing" class="hidden">
|
<div id="typing" class="hidden">
|
||||||
<p id="typingtext">typing</p>
|
<p id="typingtext">typing</p>
|
||||||
<div class="loading-indicator">
|
<div class="loading-indicator">
|
||||||
|
|
|
@ -122,7 +122,7 @@ async function enter(event){
|
||||||
if(event.key === "Enter"&&!event.shiftKey){
|
if(event.key === "Enter"&&!event.shiftKey){
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if(channel.editing){
|
if(channel.editing){
|
||||||
channel.editing.edit((typebox).value);
|
channel.editing.edit(markdown.rawString);
|
||||||
channel.editing=null;
|
channel.editing=null;
|
||||||
}else{
|
}else{
|
||||||
replyingto= thisuser.channelfocus.replyingto;
|
replyingto= thisuser.channelfocus.replyingto;
|
||||||
|
@ -131,7 +131,7 @@ async function enter(event){
|
||||||
replyingto.div.classList.remove("replying");
|
replyingto.div.classList.remove("replying");
|
||||||
}
|
}
|
||||||
thisuser.channelfocus.replyingto=null;
|
thisuser.channelfocus.replyingto=null;
|
||||||
channel.sendMessage(typebox.value,{
|
channel.sendMessage(markdown.rawString,{
|
||||||
attachments:images,
|
attachments:images,
|
||||||
replyingto:replying,
|
replyingto:replying,
|
||||||
})
|
})
|
||||||
|
@ -141,12 +141,15 @@ async function enter(event){
|
||||||
images.pop();
|
images.pop();
|
||||||
pasteimage.removeChild(imageshtml.pop());
|
pasteimage.removeChild(imageshtml.pop());
|
||||||
}
|
}
|
||||||
typebox.value="";
|
typebox.innerHTML="";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const typebox=document.getElementById("typebox") as HTMLInputElement;
|
const typebox=document.getElementById("typebox") as HTMLDivElement;
|
||||||
|
const markdown=new MarkDown("",thisuser);
|
||||||
|
markdown.giveBox(typebox);
|
||||||
|
typebox["markdown"]=markdown;
|
||||||
typebox.addEventListener("keyup",enter);
|
typebox.addEventListener("keyup",enter);
|
||||||
typebox.addEventListener("keydown",event=>{
|
typebox.addEventListener("keydown",event=>{
|
||||||
if(event.key === "Enter"&&!event.shiftKey) event.preventDefault();
|
if(event.key === "Enter"&&!event.shiftKey) event.preventDefault();
|
||||||
|
@ -166,6 +169,7 @@ const images:Blob[]=[];
|
||||||
const imageshtml=[];
|
const imageshtml=[];
|
||||||
|
|
||||||
import { File } from "./file.js";
|
import { File } from "./file.js";
|
||||||
|
import { MarkDown } from "./markdown.js";
|
||||||
document.addEventListener('paste', async (e) => {
|
document.addEventListener('paste', async (e) => {
|
||||||
Array.from(e.clipboardData.files).forEach(async (f) => {
|
Array.from(e.clipboardData.files).forEach(async (f) => {
|
||||||
const file=File.initFromBlob(f);
|
const file=File.initFromBlob(f);
|
||||||
|
@ -183,6 +187,14 @@ function userSettings(){
|
||||||
thisuser.usersettings.show();
|
thisuser.usersettings.show();
|
||||||
}
|
}
|
||||||
document.getElementById("settings").onclick=userSettings;
|
document.getElementById("settings").onclick=userSettings;
|
||||||
|
function userConnections(){
|
||||||
|
thisuser.userConnections.show();
|
||||||
|
}
|
||||||
|
document.getElementById("connections").onclick=userConnections;
|
||||||
|
function devPortal(){
|
||||||
|
thisuser.devPortal.show();
|
||||||
|
}
|
||||||
|
document.getElementById("dev-portal").onclick=devPortal;
|
||||||
|
|
||||||
if(mobile){
|
if(mobile){
|
||||||
document.getElementById("channelw").onclick=function(){
|
document.getElementById("channelw").onclick=function(){
|
||||||
|
|
|
@ -4,9 +4,11 @@ import {Direct} from "./direct.js";
|
||||||
import {Voice} from "./audio.js";
|
import {Voice} from "./audio.js";
|
||||||
import {User} from "./user.js";
|
import {User} from "./user.js";
|
||||||
import {Member} from "./member.js";
|
import {Member} from "./member.js";
|
||||||
import {markdown} from "./markdown.js";
|
import {MarkDown} from "./markdown.js";
|
||||||
import {Fullscreen} from "./fullscreen.js";
|
import {Fullscreen} from "./fullscreen.js";
|
||||||
import {setTheme, Specialuser} from "./login.js";
|
import {setTheme, Specialuser} from "./login.js";
|
||||||
|
import { SnowFlake } from "./snowflake.js";
|
||||||
|
import { Message } from "./message.js";
|
||||||
|
|
||||||
const wsCodesRetry=new Set([4000,4003,4005,4007,4008,4009]);
|
const wsCodesRetry=new Set([4000,4003,4005,4007,4008,4009]);
|
||||||
|
|
||||||
|
@ -19,14 +21,16 @@ class Localuser{
|
||||||
info;
|
info;
|
||||||
headers:{"Content-type":string,Authorization:string};
|
headers:{"Content-type":string,Authorization:string};
|
||||||
usersettings:Fullscreen;
|
usersettings:Fullscreen;
|
||||||
|
userConnections:Fullscreen;
|
||||||
|
devPortal:Fullscreen;
|
||||||
ready;
|
ready;
|
||||||
guilds:Guild[];
|
guilds:Guild[];
|
||||||
guildids:{ [key: string]: Guild };
|
guildids:Map<string,Guild>;
|
||||||
user:User;
|
user:User;
|
||||||
status:string;
|
status:string;
|
||||||
channelfocus:Channel;
|
channelfocus:Channel;
|
||||||
lookingguild:Guild;
|
lookingguild:Guild;
|
||||||
guildhtml:Record<string, HTMLDivElement>;
|
guildhtml:Map<string, HTMLDivElement>;
|
||||||
ws:WebSocket;
|
ws:WebSocket;
|
||||||
typing:[string,number][];
|
typing:[string,number][];
|
||||||
wsinterval:NodeJS.Timeout;
|
wsinterval:NodeJS.Timeout;
|
||||||
|
@ -46,14 +50,14 @@ class Localuser{
|
||||||
this.initialized=true;
|
this.initialized=true;
|
||||||
this.ready=ready;
|
this.ready=ready;
|
||||||
this.guilds=[];
|
this.guilds=[];
|
||||||
this.guildids={};
|
this.guildids=new Map();
|
||||||
this.user=new User(ready.d.user,this);
|
this.user=new User(ready.d.user,this);
|
||||||
this.userinfo.username=this.user.username;
|
this.userinfo.username=this.user.username;
|
||||||
this.userinfo.pfpsrc=this.user.getpfpsrc();
|
this.userinfo.pfpsrc=this.user.getpfpsrc();
|
||||||
this.status=this.ready.d.user_settings.status;
|
this.status=this.ready.d.user_settings.status;
|
||||||
this.channelfocus=null;
|
this.channelfocus=null;
|
||||||
this.lookingguild=null;
|
this.lookingguild=null;
|
||||||
this.guildhtml={};
|
this.guildhtml=new Map();
|
||||||
const members={};
|
const members={};
|
||||||
for(const thing of ready.d.merged_members){
|
for(const thing of ready.d.merged_members){
|
||||||
members[thing[0].guild_id]=thing[0];
|
members[thing[0].guild_id]=thing[0];
|
||||||
|
@ -62,12 +66,12 @@ class Localuser{
|
||||||
for(const thing of ready.d.guilds){
|
for(const thing of ready.d.guilds){
|
||||||
const temp=new Guild(thing,this,members[thing.id]);
|
const temp=new Guild(thing,this,members[thing.id]);
|
||||||
this.guilds.push(temp);
|
this.guilds.push(temp);
|
||||||
this.guildids[temp.id]=temp;
|
this.guildids[temp.id.id]=temp;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const temp=new Direct(ready.d.private_channels,this);
|
const temp=new Direct(ready.d.private_channels,this);
|
||||||
this.guilds.push(temp);
|
this.guilds.push(temp);
|
||||||
this.guildids[temp.id]=temp;
|
this.guildids[temp.id.id]=temp;
|
||||||
}
|
}
|
||||||
console.log(ready.d.user_guild_settings.entries);
|
console.log(ready.d.user_guild_settings.entries);
|
||||||
|
|
||||||
|
@ -84,14 +88,16 @@ class Localuser{
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
const guildid=guild.id;
|
const guildid=guild.id;
|
||||||
this.guildids[guildid].channelids[thing.channel_id].readStateInfo(thing);
|
this.guildids[guildid.id].channelids[thing.channel_id].readStateInfo(thing);
|
||||||
}
|
}
|
||||||
this.typing=[];
|
this.typing=[];
|
||||||
}
|
}
|
||||||
outoffocus():void{
|
outoffocus():void{
|
||||||
document.getElementById("servers").textContent="";
|
document.getElementById("servers").textContent="";
|
||||||
document.getElementById("channels").textContent="";
|
document.getElementById("channels").textContent="";
|
||||||
|
if(this.channelfocus){
|
||||||
this.channelfocus.infinite.delete();
|
this.channelfocus.infinite.delete();
|
||||||
|
}
|
||||||
this.lookingguild=null;
|
this.lookingguild=null;
|
||||||
this.channelfocus=null;
|
this.channelfocus=null;
|
||||||
}
|
}
|
||||||
|
@ -100,7 +106,7 @@ class Localuser{
|
||||||
clearInterval(this.wsinterval);
|
clearInterval(this.wsinterval);
|
||||||
this.outoffocus();
|
this.outoffocus();
|
||||||
this.guilds=[];
|
this.guilds=[];
|
||||||
this.guildids={};
|
this.guildids=new Map();
|
||||||
this.ws.close(4000)
|
this.ws.close(4000)
|
||||||
}
|
}
|
||||||
async initwebsocket():Promise<void>{
|
async initwebsocket():Promise<void>{
|
||||||
|
@ -134,7 +140,7 @@ class Localuser{
|
||||||
this.ws.addEventListener('message', (event) => {
|
this.ws.addEventListener('message', (event) => {
|
||||||
|
|
||||||
|
|
||||||
try{
|
|
||||||
const temp=JSON.parse(event.data);
|
const temp=JSON.parse(event.data);
|
||||||
console.log(temp)
|
console.log(temp)
|
||||||
if(temp.op==0){
|
if(temp.op==0){
|
||||||
|
@ -146,7 +152,7 @@ class Localuser{
|
||||||
break;
|
break;
|
||||||
case "MESSAGE_DELETE":
|
case "MESSAGE_DELETE":
|
||||||
console.log(temp.d);
|
console.log(temp.d);
|
||||||
this.guildids[temp.d.guild_id].channelids[temp.d.channel_id].messageids[temp.d.id].deleteEvent();
|
SnowFlake.getSnowFlakeFromID(temp.d.id,Message).getObject().deleteEvent();
|
||||||
break;
|
break;
|
||||||
case "READY":
|
case "READY":
|
||||||
this.gottenReady(temp);
|
this.gottenReady(temp);
|
||||||
|
@ -154,7 +160,7 @@ class Localuser{
|
||||||
returny();
|
returny();
|
||||||
break;
|
break;
|
||||||
case "MESSAGE_UPDATE":
|
case "MESSAGE_UPDATE":
|
||||||
const message=this.resolveChannelFromID(temp.d.channel_id).messageids[temp.d.id];
|
const message=SnowFlake.getSnowFlakeFromID(temp.d.id,Message).getObject();
|
||||||
message.giveData(temp.d);
|
message.giveData(temp.d);
|
||||||
break;
|
break;
|
||||||
case "TYPING_START":
|
case "TYPING_START":
|
||||||
|
@ -164,7 +170,7 @@ class Localuser{
|
||||||
break;
|
break;
|
||||||
case "USER_UPDATE":
|
case "USER_UPDATE":
|
||||||
if(this.initialized){
|
if(this.initialized){
|
||||||
const users=User.userids[temp.d.id];
|
const users=SnowFlake.getSnowFlakeFromID(temp.d.id,User).getObject() as User;
|
||||||
console.log(users,temp.d.id)
|
console.log(users,temp.d.id)
|
||||||
if(users){
|
if(users){
|
||||||
users.userupdate(temp.d);
|
users.userupdate(temp.d);
|
||||||
|
@ -198,7 +204,7 @@ class Localuser{
|
||||||
{
|
{
|
||||||
const guildy=new Guild(temp.d,this,this.user);
|
const guildy=new Guild(temp.d,this,this.user);
|
||||||
this.guilds.push(guildy);
|
this.guilds.push(guildy);
|
||||||
this.guildids[guildy.id]=guildy;
|
this.guildids[guildy.id.id]=guildy;
|
||||||
document.getElementById("servers").insertBefore(guildy.generateGuildIcon(),document.getElementById("bottomseparator"));
|
document.getElementById("servers").insertBefore(guildy.generateGuildIcon(),document.getElementById("bottomseparator"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -214,9 +220,7 @@ class Localuser{
|
||||||
}else if(temp.op!=11){
|
}else if(temp.op!=11){
|
||||||
this.packets++
|
this.packets++
|
||||||
}
|
}
|
||||||
}catch(error){
|
|
||||||
console.error(error)
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -260,15 +264,15 @@ class Localuser{
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
updateChannel(JSON):void{
|
updateChannel(JSON):void{
|
||||||
this.guildids[JSON.guild_id].updateChannel(JSON);
|
SnowFlake.getSnowFlakeFromID(JSON.guild_id,Guild).getObject().updateChannel(JSON);
|
||||||
if(JSON.guild_id===this.lookingguild.id){
|
if(JSON.guild_id===this.lookingguild.id.id){
|
||||||
this.loadGuild(JSON.guild_id);
|
this.loadGuild(JSON.guild_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
createChannel(JSON):void{
|
createChannel(JSON):void{
|
||||||
JSON.guild_id??="@me";
|
JSON.guild_id??="@me";
|
||||||
this.guildids[JSON.guild_id].createChannelpac(JSON);
|
SnowFlake.getSnowFlakeFromID(JSON.guild_id,Guild).getObject().createChannelpac(JSON);
|
||||||
if(JSON.guild_id===this.lookingguild.id){
|
if(JSON.guild_id===this.lookingguild.id.id){
|
||||||
this.loadGuild(JSON.guild_id);
|
this.loadGuild(JSON.guild_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -493,8 +497,8 @@ class Localuser{
|
||||||
unreads():void{
|
unreads():void{
|
||||||
console.log(this.guildhtml)
|
console.log(this.guildhtml)
|
||||||
for(const thing of this.guilds){
|
for(const thing of this.guilds){
|
||||||
if(thing.id==="@me"){continue;}
|
if(thing.id.id==="@me"){continue;}
|
||||||
thing.unreads(this.guildhtml[thing.id]);
|
thing.unreads(this.guildhtml[thing.id.id]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
typingStart(typing):void{
|
typingStart(typing):void{
|
||||||
|
@ -531,7 +535,7 @@ class Localuser{
|
||||||
reader.readAsDataURL(file);
|
reader.readAsDataURL(file);
|
||||||
console.log(this.headers);
|
console.log(this.headers);
|
||||||
reader.onload = ()=>{
|
reader.onload = ()=>{
|
||||||
fetch(this.info.api.toString()+"/v9/users/@me",{
|
fetch(this.info.api.toString()+"/users/@me",{
|
||||||
method:"PATCH",
|
method:"PATCH",
|
||||||
headers:this.headers,
|
headers:this.headers,
|
||||||
body:JSON.stringify({
|
body:JSON.stringify({
|
||||||
|
@ -543,7 +547,7 @@ class Localuser{
|
||||||
|
|
||||||
}
|
}
|
||||||
updatepronouns(pronouns:string):void{
|
updatepronouns(pronouns:string):void{
|
||||||
fetch(this.info.api.toString()+"/v9/users/@me/profile",{
|
fetch(this.info.api.toString()+"/users/@me/profile",{
|
||||||
method:"PATCH",
|
method:"PATCH",
|
||||||
headers:this.headers,
|
headers:this.headers,
|
||||||
body:JSON.stringify({
|
body:JSON.stringify({
|
||||||
|
@ -620,13 +624,13 @@ class Localuser{
|
||||||
newprouns=this.value;
|
newprouns=this.value;
|
||||||
regen();
|
regen();
|
||||||
}],
|
}],
|
||||||
["mdbox","Bio:",this.user.bio,function(e){
|
["mdbox","Bio:",this.user.bio.rawString,function(e){
|
||||||
console.log(this.value);
|
console.log(this.value);
|
||||||
hypouser.bio=this.value;
|
hypouser.bio=this.value;
|
||||||
newbio=this.value;
|
newbio=this.value;
|
||||||
regen();
|
regen();
|
||||||
}],
|
}],
|
||||||
["button","update user content:","submit",function(){
|
["button","update user content:","submit",()=>{
|
||||||
if(file!==null){
|
if(file!==null){
|
||||||
this.updatepfp(file);
|
this.updatepfp(file);
|
||||||
}
|
}
|
||||||
|
@ -657,6 +661,262 @@ class Localuser{
|
||||||
newprouns=null;
|
newprouns=null;
|
||||||
newbio=null;
|
newbio=null;
|
||||||
}.bind(this))
|
}.bind(this))
|
||||||
|
|
||||||
|
const connectionContainer=document.createElement("div");
|
||||||
|
connectionContainer.id="connection-container";
|
||||||
|
this.userConnections=new Fullscreen(
|
||||||
|
["html",
|
||||||
|
connectionContainer
|
||||||
|
], () => {}, async () => {
|
||||||
|
connectionContainer.innerHTML="";
|
||||||
|
|
||||||
|
const res=await fetch(this.info.api.toString()+"/v9/connections", {
|
||||||
|
headers: this.headers
|
||||||
|
});
|
||||||
|
const json=await res.json();
|
||||||
|
|
||||||
|
Object.keys(json).sort(key => json[key].enabled ? -1 : 1).forEach(key => {
|
||||||
|
const connection=json[key];
|
||||||
|
|
||||||
|
const container=document.createElement("div");
|
||||||
|
container.textContent=key.charAt(0).toUpperCase() + key.slice(1);
|
||||||
|
|
||||||
|
if (connection.enabled) {
|
||||||
|
container.addEventListener("click", async () => {
|
||||||
|
const connectionRes=await fetch(this.info.api.toString()+"/v9/connections/" + key + "/authorize", {
|
||||||
|
headers: this.headers
|
||||||
|
});
|
||||||
|
const connectionJSON=await connectionRes.json();
|
||||||
|
window.open(connectionJSON.url, "_blank", "noopener noreferrer");
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
container.classList.add("disabled")
|
||||||
|
container.title="This connection has been disabled server-side."
|
||||||
|
}
|
||||||
|
|
||||||
|
connectionContainer.appendChild(container);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
let appName="";
|
||||||
|
const appListContainer=document.createElement("div");
|
||||||
|
appListContainer.id="app-list-container";
|
||||||
|
this.devPortal=new Fullscreen(
|
||||||
|
["vdiv",
|
||||||
|
["hdiv",
|
||||||
|
["textbox", "Name:", appName, event => {
|
||||||
|
appName=event.target.value;
|
||||||
|
}],
|
||||||
|
["button",
|
||||||
|
"",
|
||||||
|
"Create application",
|
||||||
|
async () => {
|
||||||
|
if (appName.trim().length == 0) return alert("Please enter a name for the application.");
|
||||||
|
|
||||||
|
const res=await fetch(this.info.api.toString()+"/v9/applications", {
|
||||||
|
method: "POST",
|
||||||
|
headers: this.headers,
|
||||||
|
body: JSON.stringify({
|
||||||
|
name: appName
|
||||||
|
})
|
||||||
|
});
|
||||||
|
const json=await res.json();
|
||||||
|
this.manageApplication(json.id);
|
||||||
|
this.devPortal.hide();
|
||||||
|
}
|
||||||
|
]
|
||||||
|
],
|
||||||
|
["html",
|
||||||
|
appListContainer
|
||||||
|
]
|
||||||
|
], () => {}, async () => {
|
||||||
|
appListContainer.innerHTML="";
|
||||||
|
|
||||||
|
const res=await fetch(this.info.api.toString()+"/v9/applications", {
|
||||||
|
headers: this.headers
|
||||||
|
});
|
||||||
|
const json=await res.json();
|
||||||
|
|
||||||
|
json.forEach(application => {
|
||||||
|
const container=document.createElement("div");
|
||||||
|
|
||||||
|
if (application.cover_image) {
|
||||||
|
const cover=document.createElement("img");
|
||||||
|
cover.crossOrigin="anonymous";
|
||||||
|
cover.src=this.info.cdn.toString()+"/app-icons/" + application.id + "/" + application.cover_image + ".png?size=256";
|
||||||
|
cover.alt="";
|
||||||
|
cover.loading="lazy";
|
||||||
|
container.appendChild(cover);
|
||||||
|
}
|
||||||
|
|
||||||
|
const name=document.createElement("h2");
|
||||||
|
name.textContent=application.name + (application.bot ? " (Bot)" : "");
|
||||||
|
container.appendChild(name);
|
||||||
|
|
||||||
|
container.addEventListener("click", async () => {
|
||||||
|
this.devPortal.hide();
|
||||||
|
this.manageApplication(application.id);
|
||||||
|
});
|
||||||
|
appListContainer.appendChild(container);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
async manageApplication(appId="") {
|
||||||
|
const res=await fetch(this.info.api.toString()+"/v9/applications/" + appId, {
|
||||||
|
headers: this.headers
|
||||||
|
});
|
||||||
|
const json=await res.json();
|
||||||
|
|
||||||
|
const fields: any={};
|
||||||
|
const appDialog=new Fullscreen(
|
||||||
|
["vdiv",
|
||||||
|
["title",
|
||||||
|
"Editing " + json.name
|
||||||
|
],
|
||||||
|
["vdiv",
|
||||||
|
["textbox", "Application name:", json.name, event => {
|
||||||
|
fields.name=event.target.value;
|
||||||
|
}],
|
||||||
|
["mdbox", "Description:", json.description, event => {
|
||||||
|
fields.description=event.target.value;
|
||||||
|
}],
|
||||||
|
["vdiv",
|
||||||
|
json.icon ? ["img", this.info.cdn.toString()+"/app-icons/" + appId + "/" + json.icon + ".png?size=128", [128, 128]] : ["text", "No icon"],
|
||||||
|
["fileupload", "Application icon:", event => {
|
||||||
|
const reader=new FileReader();
|
||||||
|
reader.readAsDataURL(event.target.files[0]);
|
||||||
|
reader.onload=() => {
|
||||||
|
fields.icon=reader.result;
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
["hdiv",
|
||||||
|
["textbox", "Privacy policy URL:", json.privacy_policy_url || "", event => {
|
||||||
|
fields.privacy_policy_url=event.target.value;
|
||||||
|
}],
|
||||||
|
["textbox", "Terms of Service URL:", json.terms_of_service_url || "", event => {
|
||||||
|
fields.terms_of_service_url=event.target.value;
|
||||||
|
}]
|
||||||
|
],
|
||||||
|
["hdiv",
|
||||||
|
["checkbox", "Make bot publicly inviteable?", json.bot_public, event => {
|
||||||
|
fields.bot_public=event.target.checked;
|
||||||
|
}],
|
||||||
|
["checkbox", "Require code grant to invite the bot?", json.bot_require_code_grant, event => {
|
||||||
|
fields.bot_require_code_grant=event.target.checked;
|
||||||
|
}]
|
||||||
|
],
|
||||||
|
["hdiv",
|
||||||
|
["button",
|
||||||
|
"",
|
||||||
|
"Save changes",
|
||||||
|
async () => {
|
||||||
|
const updateRes=await fetch(this.info.api.toString()+"/v9/applications/" + appId, {
|
||||||
|
method: "PATCH",
|
||||||
|
headers: this.headers,
|
||||||
|
body: JSON.stringify(fields)
|
||||||
|
});
|
||||||
|
if (updateRes.ok) appDialog.hide();
|
||||||
|
else {
|
||||||
|
const updateJSON=await updateRes.json();
|
||||||
|
alert("An error occurred: " + updateJSON.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
["button",
|
||||||
|
"",
|
||||||
|
(json.bot ? "Manage" : "Add") + " bot",
|
||||||
|
async () => {
|
||||||
|
if (!json.bot) {
|
||||||
|
if (!confirm("Are you sure you want to add a bot to this application? There's no going back.")) return;
|
||||||
|
|
||||||
|
const updateRes=await fetch(this.info.api.toString()+"/v9/applications/" + appId + "/bot", {
|
||||||
|
method: "POST",
|
||||||
|
headers: this.headers
|
||||||
|
});
|
||||||
|
const updateJSON=await updateRes.json();
|
||||||
|
alert("Bot token:\n" + updateJSON.token);
|
||||||
|
}
|
||||||
|
|
||||||
|
appDialog.hide();
|
||||||
|
this.manageBot(appId);
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
)
|
||||||
|
appDialog.show();
|
||||||
|
}
|
||||||
|
async manageBot(appId="") {
|
||||||
|
const res=await fetch(this.info.api.toString()+"/v9/applications/" + appId, {
|
||||||
|
headers: this.headers
|
||||||
|
});
|
||||||
|
const json=await res.json();
|
||||||
|
if (!json.bot) return alert("For some reason, this application doesn't have a bot (yet).");
|
||||||
|
|
||||||
|
const fields: any={
|
||||||
|
username: json.bot.username,
|
||||||
|
avatar: json.bot.avatar ? (this.info.cdn.toString()+"/app-icons/" + appId + "/" + json.bot.avatar + ".png?size=256") : ""
|
||||||
|
};
|
||||||
|
const botDialog=new Fullscreen(
|
||||||
|
["vdiv",
|
||||||
|
["title",
|
||||||
|
"Editing bot: " + json.bot.username
|
||||||
|
],
|
||||||
|
["hdiv",
|
||||||
|
["textbox", "Bot username:", json.bot.username, event => {
|
||||||
|
fields.username=event.target.value
|
||||||
|
}],
|
||||||
|
["vdiv",
|
||||||
|
fields.avatar ? ["img", fields.avatar, [128, 128]] : ["text", "No avatar"],
|
||||||
|
["fileupload", "Bot avatar:", event => {
|
||||||
|
const reader=new FileReader();
|
||||||
|
reader.readAsDataURL(event.target.files[0]);
|
||||||
|
reader.onload=() => {
|
||||||
|
fields.avatar=reader.result;
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
["hdiv",
|
||||||
|
["button",
|
||||||
|
"",
|
||||||
|
"Save changes",
|
||||||
|
async () => {
|
||||||
|
const updateRes=await fetch(this.info.api.toString()+"/v9/applications/" + appId + "/bot", {
|
||||||
|
method: "PATCH",
|
||||||
|
headers: this.headers,
|
||||||
|
body: JSON.stringify(fields)
|
||||||
|
});
|
||||||
|
if (updateRes.ok) botDialog.hide();
|
||||||
|
else {
|
||||||
|
const updateJSON=await updateRes.json();
|
||||||
|
alert("An error occurred: " + updateJSON.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
["button",
|
||||||
|
"",
|
||||||
|
"Reset token",
|
||||||
|
async () => {
|
||||||
|
if (!confirm("Are you sure you want to reset the bot token? Your bot will stop working until you update it.")) return;
|
||||||
|
|
||||||
|
const updateRes=await fetch(this.info.api.toString()+"/v9/applications/" + appId + "/bot/reset", {
|
||||||
|
method: "POST",
|
||||||
|
headers: this.headers
|
||||||
|
});
|
||||||
|
const updateJSON=await updateRes.json();
|
||||||
|
alert("New token:\n" + updateJSON.token);
|
||||||
|
botDialog.hide();
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
);
|
||||||
|
botDialog.show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export {Localuser};
|
export {Localuser};
|
||||||
|
|
|
@ -1,5 +1,37 @@
|
||||||
export {markdown};
|
import { Channel } from "./channel";
|
||||||
function markdown(text : string|string[],{keep=false,stdsize=false} = {}){
|
import { Localuser } from "./localuser";
|
||||||
|
|
||||||
|
export {MarkDown};
|
||||||
|
class MarkDown{
|
||||||
|
txt : string[];
|
||||||
|
keep:boolean;
|
||||||
|
stdsize:boolean;
|
||||||
|
owner:Localuser|Channel;
|
||||||
|
info:Localuser["info"];
|
||||||
|
constructor(text : string|string[],owner:MarkDown["owner"],{keep=false,stdsize=false} = {}){
|
||||||
|
if((typeof text)===(typeof "")){
|
||||||
|
this.txt=(text as string).split("");
|
||||||
|
}else{
|
||||||
|
this.txt=(text as string[]);
|
||||||
|
}
|
||||||
|
if(this.txt===undefined){
|
||||||
|
this.txt=[];
|
||||||
|
}
|
||||||
|
this.info=owner.info;
|
||||||
|
this.keep=keep;
|
||||||
|
this.owner=owner;
|
||||||
|
this.stdsize=stdsize;
|
||||||
|
}
|
||||||
|
get rawString(){
|
||||||
|
return this.txt.join("");
|
||||||
|
}
|
||||||
|
get textContent(){
|
||||||
|
return this.makeHTML().textContent;
|
||||||
|
}
|
||||||
|
makeHTML({keep=this.keep,stdsize=this.stdsize}={}){
|
||||||
|
return this.markdown(this.txt,{keep:keep,stdsize:stdsize});
|
||||||
|
}
|
||||||
|
markdown(text : string|string[],{keep=false,stdsize=false} = {}){
|
||||||
let txt : string[];
|
let txt : string[];
|
||||||
if((typeof text)===(typeof "")){
|
if((typeof text)===(typeof "")){
|
||||||
txt=(text as string).split("");
|
txt=(text as string).split("");
|
||||||
|
@ -69,9 +101,10 @@ function markdown(text : string|string[],{keep=false,stdsize=false} = {}){
|
||||||
if(keep){
|
if(keep){
|
||||||
element.append(keepys);
|
element.append(keepys);
|
||||||
}
|
}
|
||||||
element.appendChild(markdown(build,{keep:keep,stdsize:stdsize}));
|
element.appendChild(this.markdown(build,{keep:keep,stdsize:stdsize}));
|
||||||
span.append(element);
|
span.append(element);
|
||||||
i--;
|
i-=1;
|
||||||
|
console.log(txt[i]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(first){
|
if(first){
|
||||||
|
@ -183,20 +216,20 @@ function markdown(text : string|string[],{keep=false,stdsize=false} = {}){
|
||||||
if(count===1){
|
if(count===1){
|
||||||
const i=document.createElement("i");
|
const i=document.createElement("i");
|
||||||
if(keep){i.append(stars)}
|
if(keep){i.append(stars)}
|
||||||
i.appendChild(markdown(build,{keep:keep,stdsize:stdsize}));
|
i.appendChild(this.markdown(build,{keep:keep,stdsize:stdsize}));
|
||||||
if(keep){i.append(stars)}
|
if(keep){i.append(stars)}
|
||||||
span.appendChild(i);
|
span.appendChild(i);
|
||||||
}else if(count===2){
|
}else if(count===2){
|
||||||
const b=document.createElement("b");
|
const b=document.createElement("b");
|
||||||
if(keep){b.append(stars)}
|
if(keep){b.append(stars)}
|
||||||
b.appendChild(markdown(build,{keep:keep,stdsize:stdsize}));
|
b.appendChild(this.markdown(build,{keep:keep,stdsize:stdsize}));
|
||||||
if(keep){b.append(stars)}
|
if(keep){b.append(stars)}
|
||||||
span.appendChild(b);
|
span.appendChild(b);
|
||||||
}else{
|
}else{
|
||||||
const b=document.createElement("b");
|
const b=document.createElement("b");
|
||||||
const i=document.createElement("i");
|
const i=document.createElement("i");
|
||||||
if(keep){b.append(stars)}
|
if(keep){b.append(stars)}
|
||||||
b.appendChild(markdown(build,{keep:keep,stdsize:stdsize}));
|
b.appendChild(this.markdown(build,{keep:keep,stdsize:stdsize}));
|
||||||
if(keep){b.append(stars)}
|
if(keep){b.append(stars)}
|
||||||
i.appendChild(b);
|
i.appendChild(b);
|
||||||
span.appendChild(i);
|
span.appendChild(i);
|
||||||
|
@ -236,20 +269,20 @@ function markdown(text : string|string[],{keep=false,stdsize=false} = {}){
|
||||||
if(count===1){
|
if(count===1){
|
||||||
const i=document.createElement("i");
|
const i=document.createElement("i");
|
||||||
if(keep){i.append(underscores)}
|
if(keep){i.append(underscores)}
|
||||||
i.appendChild(markdown(build,{keep:keep,stdsize:stdsize}));
|
i.appendChild(this.markdown(build,{keep:keep,stdsize:stdsize}));
|
||||||
if(keep){i.append(underscores)}
|
if(keep){i.append(underscores)}
|
||||||
span.appendChild(i);
|
span.appendChild(i);
|
||||||
}else if(count===2){
|
}else if(count===2){
|
||||||
const u=document.createElement("u");
|
const u=document.createElement("u");
|
||||||
if(keep){u.append(underscores)}
|
if(keep){u.append(underscores)}
|
||||||
u.appendChild(markdown(build,{keep:keep,stdsize:stdsize}));
|
u.appendChild(this.markdown(build,{keep:keep,stdsize:stdsize}));
|
||||||
if(keep){u.append(underscores)}
|
if(keep){u.append(underscores)}
|
||||||
span.appendChild(u);
|
span.appendChild(u);
|
||||||
}else{
|
}else{
|
||||||
const u=document.createElement("u");
|
const u=document.createElement("u");
|
||||||
const i=document.createElement("i");
|
const i=document.createElement("i");
|
||||||
if(keep){i.append(underscores)}
|
if(keep){i.append(underscores)}
|
||||||
i.appendChild(markdown(build,{keep:keep,stdsize:stdsize}));
|
i.appendChild(this.markdown(build,{keep:keep,stdsize:stdsize}));
|
||||||
if(keep){i.append(underscores)}
|
if(keep){i.append(underscores)}
|
||||||
u.appendChild(i)
|
u.appendChild(i)
|
||||||
span.appendChild(u);
|
span.appendChild(u);
|
||||||
|
@ -277,12 +310,12 @@ function markdown(text : string|string[],{keep=false,stdsize=false} = {}){
|
||||||
}
|
}
|
||||||
if(find===count){
|
if(find===count){
|
||||||
appendcurrent();
|
appendcurrent();
|
||||||
i=j;
|
i=j-1;
|
||||||
const tildes="~~";
|
const tildes="~~";
|
||||||
if(count===2){
|
if(count===2){
|
||||||
const s=document.createElement("s");
|
const s=document.createElement("s");
|
||||||
if(keep){s.append(tildes)}
|
if(keep){s.append(tildes)}
|
||||||
s.appendChild(markdown(build,{keep:keep,stdsize:stdsize}));
|
s.appendChild(this.markdown(build,{keep:keep,stdsize:stdsize}));
|
||||||
if(keep){s.append(tildes)}
|
if(keep){s.append(tildes)}
|
||||||
span.appendChild(s);
|
span.appendChild(s);
|
||||||
}
|
}
|
||||||
|
@ -307,14 +340,14 @@ function markdown(text : string|string[],{keep=false,stdsize=false} = {}){
|
||||||
}
|
}
|
||||||
if(find===count){
|
if(find===count){
|
||||||
appendcurrent();
|
appendcurrent();
|
||||||
i=j;
|
i=j-1;
|
||||||
const pipes="||";
|
const pipes="||";
|
||||||
if(count===2){
|
if(count===2){
|
||||||
const j=document.createElement("j");
|
const j=document.createElement("j");
|
||||||
if(keep){j.append(pipes)}
|
if(keep){j.append(pipes)}
|
||||||
j.appendChild(markdown(build,{keep:keep,stdsize:stdsize}));
|
j.appendChild(this.markdown(build,{keep:keep,stdsize:stdsize}));
|
||||||
j.classList.add("spoiler");
|
j.classList.add("spoiler");
|
||||||
j.onclick=markdown.unspoil;
|
j.onclick=MarkDown.unspoil;
|
||||||
if(keep){j.append(pipes)}
|
if(keep){j.append(pipes)}
|
||||||
span.appendChild(j);
|
span.appendChild(j);
|
||||||
}
|
}
|
||||||
|
@ -377,21 +410,20 @@ function markdown(text : string|string[],{keep=false,stdsize=false} = {}){
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found) {
|
if (found) {
|
||||||
const parts=build.join("").match(/^<(a)?:\w+:(\d{10,30})>$/);
|
const buildjoin=build.join("");
|
||||||
|
const parts=buildjoin.match(/^<(a)?:\w+:(\d{10,30})>$/);
|
||||||
if (parts && parts[2]) {
|
if (parts && parts[2]) {
|
||||||
appendcurrent();
|
appendcurrent();
|
||||||
i=j;
|
i=j;
|
||||||
console.log(typeof txt,txt);
|
const isEmojiOnly = txt.join("").trim()===buildjoin.trim();
|
||||||
const isEmojiOnly = txt.join("").trim()===build.join("").trim();
|
|
||||||
|
|
||||||
const emojiElem=document.createElement("img");
|
const emojiElem=document.createElement("img");
|
||||||
emojiElem.classList.add("md-emoji");
|
emojiElem.classList.add("md-emoji");
|
||||||
emojiElem.width=isEmojiOnly ? 48 : 22;
|
emojiElem.classList.add(isEmojiOnly ? "bigemoji" : "smallemoji");
|
||||||
emojiElem.height=isEmojiOnly ? 48 : 22;
|
|
||||||
emojiElem.crossOrigin="anonymous";
|
emojiElem.crossOrigin="anonymous";
|
||||||
//emojiElem.src=this.info.cdn.toString() + "/emojis/" + parts[2] + "." + (parts[1] ? "gif" : "png") + "?size=32";
|
emojiElem.src=this.info.cdn.toString() + "emojis/" + parts[2] + "." + (parts[1] ? "gif" : "png") + "?size=32";
|
||||||
//must uncomment later
|
|
||||||
emojiElem.alt="";
|
emojiElem.alt=buildjoin;
|
||||||
emojiElem.loading="lazy";
|
emojiElem.loading="lazy";
|
||||||
span.appendChild(emojiElem);
|
span.appendChild(emojiElem);
|
||||||
|
|
||||||
|
@ -404,10 +436,96 @@ function markdown(text : string|string[],{keep=false,stdsize=false} = {}){
|
||||||
}
|
}
|
||||||
appendcurrent();
|
appendcurrent();
|
||||||
return span;
|
return span;
|
||||||
}
|
}
|
||||||
markdown.unspoil=function(e:any) : void{
|
static unspoil(e:any) : void{
|
||||||
//console.log("undone")
|
e.target.classList.remove("spoiler");
|
||||||
e.target.classList.remove("spoiler")
|
e.target.classList.add("unspoiled");
|
||||||
e.target.classList.add("unspoiled")
|
}
|
||||||
|
giveBox(box:HTMLDivElement){
|
||||||
|
box.onkeydown=_=>{
|
||||||
|
//console.log(_);
|
||||||
|
};
|
||||||
|
let prevcontent="";
|
||||||
|
box.onkeyup=_=>{
|
||||||
|
const content=MarkDown.gatherBoxText(box);
|
||||||
|
if(content!==prevcontent){
|
||||||
|
prevcontent=content;
|
||||||
|
this.txt=content.split("");
|
||||||
|
this.boxupdate(box);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
box.onpaste=_=>{
|
||||||
|
console.log(_.clipboardData.types)
|
||||||
|
const data=_.clipboardData.getData("text");
|
||||||
|
|
||||||
|
document.execCommand('insertHTML', false, data);
|
||||||
|
_.preventDefault();
|
||||||
|
box.onkeyup(new KeyboardEvent("_"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
boxupdate(box:HTMLElement){
|
||||||
|
var restore = saveCaretPosition(box);
|
||||||
|
box.innerHTML="";
|
||||||
|
box.append(this.makeHTML({keep:true}))
|
||||||
|
restore();
|
||||||
|
}
|
||||||
|
static gatherBoxText(element:HTMLElement){
|
||||||
|
const children=element.childNodes;
|
||||||
|
if(element.tagName.toLowerCase()==="img"){
|
||||||
|
return (element as HTMLImageElement).alt;
|
||||||
|
}
|
||||||
|
if(element.tagName.toLowerCase()==="br"){
|
||||||
|
return "\n";
|
||||||
|
}
|
||||||
|
if(children.length!==0){
|
||||||
|
let build="";
|
||||||
|
for(const thing of children){
|
||||||
|
|
||||||
|
if(thing instanceof Text){
|
||||||
|
|
||||||
|
const text=thing.textContent;
|
||||||
|
build+=text;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const text=this.gatherBoxText(thing as HTMLElement);
|
||||||
|
if(text){
|
||||||
|
build+=text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return build;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//solution from https://stackoverflow.com/questions/4576694/saving-and-restoring-caret-position-for-contenteditable-div
|
||||||
|
function saveCaretPosition(context){
|
||||||
|
var selection = window.getSelection();
|
||||||
|
var range = selection.getRangeAt(0);
|
||||||
|
range.setStart( context, 0 );
|
||||||
|
var len = range.toString().length;
|
||||||
|
|
||||||
|
return function restore(){
|
||||||
|
var pos = getTextNodeAtPosition(context, len);
|
||||||
|
selection.removeAllRanges();
|
||||||
|
var range = new Range();
|
||||||
|
range.setStart(pos.node ,pos.position);
|
||||||
|
selection.addRange(range);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTextNodeAtPosition(root, index){
|
||||||
|
const NODE_TYPE = NodeFilter.SHOW_TEXT;
|
||||||
|
var treeWalker = document.createTreeWalker(root, NODE_TYPE, function next(elem) {
|
||||||
|
if(index > elem.textContent.length){
|
||||||
|
index -= elem.textContent.length;
|
||||||
|
return NodeFilter.FILTER_REJECT
|
||||||
|
}
|
||||||
|
return NodeFilter.FILTER_ACCEPT;
|
||||||
|
});
|
||||||
|
var c = treeWalker.nextNode();
|
||||||
|
return {
|
||||||
|
node: c? c: root,
|
||||||
|
position: index
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ import {User} from "./user.js";
|
||||||
import {Role} from "./role.js";
|
import {Role} from "./role.js";
|
||||||
import {Guild} from "./guild.js";
|
import {Guild} from "./guild.js";
|
||||||
import { Contextmenu } from "./contextmenu.js";
|
import { Contextmenu } from "./contextmenu.js";
|
||||||
|
import { SnowFlake } from "./snowflake.js";
|
||||||
|
|
||||||
class Member{
|
class Member{
|
||||||
static already={};
|
static already={};
|
||||||
|
@ -38,7 +39,7 @@ class Member{
|
||||||
if(thing==="owner"){continue}
|
if(thing==="owner"){continue}
|
||||||
if(thing==="roles"){
|
if(thing==="roles"){
|
||||||
for(const strrole of membery["roles"]){
|
for(const strrole of membery["roles"]){
|
||||||
const role=this.guild.getRole(strrole);
|
const role=SnowFlake.getSnowFlakeFromID(strrole,Role).getObject();
|
||||||
this.roles.push(role);
|
this.roles.push(role);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
@ -65,44 +66,45 @@ class Member{
|
||||||
console.error(guild)
|
console.error(guild)
|
||||||
}
|
}
|
||||||
let user:User;
|
let user:User;
|
||||||
let id="";
|
let id:SnowFlake<User>;
|
||||||
if(unkown instanceof User){
|
if(unkown instanceof User){
|
||||||
user=unkown as User;
|
user=unkown as User;
|
||||||
id=user.id;
|
id=user.id;
|
||||||
}else if(typeof unkown===typeof ""){
|
}else if(typeof unkown===typeof ""){
|
||||||
id=unkown as string;
|
id=new SnowFlake(unkown as string,undefined);
|
||||||
}else{
|
}else{
|
||||||
return new Member(unkown,guild);
|
return new Member(unkown,guild);
|
||||||
}
|
}
|
||||||
if(guild.id==="@me"){return null}
|
if(guild.id.id==="@me"){return null}
|
||||||
if(!Member.already[guild.id]){
|
if(!Member.already[guild.id.id]){
|
||||||
Member.already[guild.id]={};
|
Member.already[guild.id.id]={};
|
||||||
}else if(Member.already[guild.id][id]){
|
}else if(Member.already[guild.id.id][id]){
|
||||||
const memb=Member.already[guild.id][id]
|
const memb=Member.already[guild.id.id][id]
|
||||||
if(memb instanceof Promise){
|
if(memb instanceof Promise){
|
||||||
return await memb;
|
return await memb;
|
||||||
}
|
}
|
||||||
return memb;
|
return memb;
|
||||||
}
|
}
|
||||||
const promoise= fetch(guild.info.api.toString()+"/v9/users/"+id+"/profile?with_mutual_guilds=true&with_mutual_friends_count=true&guild_id="+guild.id,{headers:guild.headers}).then(_=>_.json()).then(json=>{
|
const promoise= fetch(guild.info.api.toString()+"/users/"+id+"/profile?with_mutual_guilds=true&with_mutual_friends_count=true&guild_id="+guild.id,{headers:guild.headers}).then(_=>_.json()).then(json=>{
|
||||||
const memb=new Member(json,guild);
|
const memb=new Member(json,guild);
|
||||||
Member.already[guild.id][id]=memb;
|
Member.already[guild.id.id][id]=memb;
|
||||||
console.log("resolved")
|
console.log("resolved")
|
||||||
return memb
|
return memb
|
||||||
})
|
})
|
||||||
Member.already[guild.id][id]=promoise;
|
Member.already[guild.id.id][id]=promoise;
|
||||||
try{
|
try{
|
||||||
return await promoise
|
return await promoise
|
||||||
}catch(_){
|
}catch(_){
|
||||||
|
|
||||||
const memb=new Member(user,guild,true);
|
const memb=new Member(user,guild,true);
|
||||||
Member.already[guild.id][id]=memb;
|
Member.already[guild.id.id][id]=memb;
|
||||||
return memb;
|
return memb;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hasRole(ID:string){
|
hasRole(ID:string){
|
||||||
console.log(this.roles,ID);
|
console.log(this.roles,ID);
|
||||||
for(const thing of this.roles){
|
for(const thing of this.roles){
|
||||||
if(thing.id===ID){
|
if(thing.id.id===ID){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,7 +125,7 @@ class Member{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this.guild.properties.owner_id===this.user.id;
|
return this.guild.properties.owner_id===this.user.id.id;
|
||||||
}
|
}
|
||||||
bind(html:HTMLElement){
|
bind(html:HTMLElement){
|
||||||
if(html.tagName==="SPAN"){
|
if(html.tagName==="SPAN"){
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
import {Contextmenu} from "./contextmenu.js";
|
import {Contextmenu} from "./contextmenu.js";
|
||||||
import {User} from "./user.js";
|
import {User} from "./user.js";
|
||||||
import {Member} from "./member.js";
|
import {Member} from "./member.js";
|
||||||
import {markdown} from "./markdown.js";
|
import {MarkDown} from "./markdown.js";
|
||||||
import {Embed} from "./embed.js";
|
import {Embed} from "./embed.js";
|
||||||
import { Channel } from "./channel.js";
|
import { Channel } from "./channel.js";
|
||||||
import {Localuser} from "./localuser.js";
|
import {Localuser} from "./localuser.js";
|
||||||
import { Role } from "./role.js";
|
import { Role } from "./role.js";
|
||||||
import {File} from "./file.js";
|
import {File} from "./file.js";
|
||||||
|
import { SnowFlake } from "./snowflake.js";
|
||||||
|
|
||||||
class Message{
|
class Message{
|
||||||
static contextmenu=new Contextmenu("message menu");
|
static contextmenu=new Contextmenu("message menu");
|
||||||
|
@ -17,11 +18,11 @@ class Message{
|
||||||
mentions:User[];
|
mentions:User[];
|
||||||
mention_roles:Role[];
|
mention_roles:Role[];
|
||||||
attachments:File[];//probably should be its own class tbh, should be Attachments[]
|
attachments:File[];//probably should be its own class tbh, should be Attachments[]
|
||||||
id:string;
|
id:SnowFlake<Message>;
|
||||||
message_reference;
|
message_reference;
|
||||||
type:number;
|
type:number;
|
||||||
timestamp:number;
|
timestamp:number;
|
||||||
content:string;
|
content:MarkDown;
|
||||||
static del:Promise<void>;
|
static del:Promise<void>;
|
||||||
static resolve:Function;
|
static resolve:Function;
|
||||||
div:HTMLDivElement;
|
div:HTMLDivElement;
|
||||||
|
@ -37,17 +38,19 @@ class Message{
|
||||||
}
|
}
|
||||||
static setupcmenu(){
|
static setupcmenu(){
|
||||||
Message.contextmenu.addbutton("Copy raw text",function(){
|
Message.contextmenu.addbutton("Copy raw text",function(){
|
||||||
navigator.clipboard.writeText(this.content);
|
navigator.clipboard.writeText(this.content.rawString);
|
||||||
});
|
});
|
||||||
Message.contextmenu.addbutton("Reply",function(this:Message,div:HTMLDivElement){
|
Message.contextmenu.addbutton("Reply",function(this:Message,div:HTMLDivElement){
|
||||||
this.channel.setReplying(this);
|
this.channel.setReplying(this);
|
||||||
});
|
});
|
||||||
Message.contextmenu.addbutton("Copy message id",function(){
|
Message.contextmenu.addbutton("Copy message id",function(){
|
||||||
navigator.clipboard.writeText(this.id);
|
navigator.clipboard.writeText(this.id.id);
|
||||||
});
|
});
|
||||||
Message.contextmenu.addbutton("Edit",function(){
|
Message.contextmenu.addbutton("Edit",function(){
|
||||||
this.channel.editing=this;
|
this.channel.editing=this;
|
||||||
(document.getElementById("typebox") as HTMLInputElement).value=this.content;
|
const markdown=(document.getElementById("typebox"))["markdown"] as MarkDown;
|
||||||
|
markdown.txt=this.content.rawString;
|
||||||
|
markdown.boxupdate(document.getElementById("typebox"));
|
||||||
},null,_=>{return _.author.id===_.localuser.user.id});
|
},null,_=>{return _.author.id===_.localuser.user.id});
|
||||||
Message.contextmenu.addbutton("Delete message",function(){
|
Message.contextmenu.addbutton("Delete message",function(){
|
||||||
this.delete();
|
this.delete();
|
||||||
|
@ -67,6 +70,12 @@ class Message{
|
||||||
this.attachments.push(new File(thing,this));
|
this.attachments.push(new File(thing,this));
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
}else if(thing==="content"){
|
||||||
|
this.content=new MarkDown(messagejson[thing],this.channel);
|
||||||
|
continue;
|
||||||
|
}else if(thing ==="id"){
|
||||||
|
this.id=new SnowFlake(messagejson.id,this);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
this[thing]=messagejson[thing];
|
this[thing]=messagejson[thing];
|
||||||
}
|
}
|
||||||
|
@ -130,14 +139,14 @@ class Message{
|
||||||
return build;
|
return build;
|
||||||
}
|
}
|
||||||
async edit(content){
|
async edit(content){
|
||||||
return await fetch(this.info.api.toString()+"/channels/"+this.channel.id+"/messages/"+this.id,{
|
return await fetch(this.info.api.toString()+"/channels/"+this.channel.id+"/messages/"+this.id.id,{
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
headers: this.headers,
|
headers: this.headers,
|
||||||
body:JSON.stringify({content:content})
|
body:JSON.stringify({content:content})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
delete(){
|
delete(){
|
||||||
fetch(`${this.info.api.toString()}/channels/${this.channel.id}/messages/${this.id}`,{
|
fetch(`${this.info.api.toString()}/channels/${this.channel.id}/messages/${this.id.id}`,{
|
||||||
headers:this.headers,
|
headers:this.headers,
|
||||||
method:"DELETE",
|
method:"DELETE",
|
||||||
})
|
})
|
||||||
|
@ -147,19 +156,22 @@ class Message{
|
||||||
this.div.innerHTML="";
|
this.div.innerHTML="";
|
||||||
this.div=null;
|
this.div=null;
|
||||||
}
|
}
|
||||||
const prev=this.channel.idToPrev[this.id];
|
const prev=this.channel.idToPrev[this.id.id];
|
||||||
const next=this.channel.idToNext[this.id];
|
const next=this.channel.idToNext[this.id.id];
|
||||||
this.channel.idToNext[prev]=next;
|
this.channel.idToNext[prev]=next;
|
||||||
this.channel.idToPrev[next]=prev;
|
this.channel.idToPrev[next]=prev;
|
||||||
delete this.channel.messageids[this.id];
|
delete this.channel.messageids[this.id.id];
|
||||||
const regen=this.channel.messageids[prev]
|
const regen=this.channel.messageids[prev]
|
||||||
if(regen){
|
if(regen){
|
||||||
regen.generateMessage();
|
regen.generateMessage();
|
||||||
}
|
}
|
||||||
|
if(this.channel.lastmessage===this){
|
||||||
|
this.channel.lastmessage=this.channel.messageids[prev];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
generateMessage(premessage:Message=null){
|
generateMessage(premessage:Message=null){
|
||||||
if(!premessage){
|
if(!premessage){
|
||||||
premessage=this.channel.messageids[this.channel.idToNext[this.id]];
|
premessage=this.channel.messageids[this.channel.idToNext[this.id.id]];
|
||||||
}
|
}
|
||||||
const div=this.div;
|
const div=this.div;
|
||||||
if(this===this.channel.replyingto){
|
if(this===this.channel.replyingto){
|
||||||
|
@ -210,7 +222,7 @@ class Message{
|
||||||
replyline.classList.add("replyflex")
|
replyline.classList.add("replyflex")
|
||||||
this.channel.getmessage(this.message_reference.message_id).then(message=>{
|
this.channel.getmessage(this.message_reference.message_id).then(message=>{
|
||||||
const author=message.author;
|
const author=message.author;
|
||||||
reply.appendChild(markdown(message.content,{stdsize:true}));
|
reply.appendChild(message.content.makeHTML({stdsize:true}));
|
||||||
minipfp.src=author.getpfpsrc()
|
minipfp.src=author.getpfpsrc()
|
||||||
author.bind(minipfp);
|
author.bind(minipfp);
|
||||||
username.textContent=author.username;
|
username.textContent=author.username;
|
||||||
|
@ -271,7 +283,7 @@ class Message{
|
||||||
}else{
|
}else{
|
||||||
div.classList.remove("topMessage");
|
div.classList.remove("topMessage");
|
||||||
}
|
}
|
||||||
const messaged=markdown(this.content);
|
const messaged=this.content.makeHTML();
|
||||||
div["txt"]=messaged;
|
div["txt"]=messaged;
|
||||||
const messagedwrap=document.createElement("div");
|
const messagedwrap=document.createElement("div");
|
||||||
messagedwrap.classList.add("flexttb")
|
messagedwrap.classList.add("flexttb")
|
||||||
|
|
|
@ -2,11 +2,12 @@ export {Role};
|
||||||
import {Permissions} from "./permissions.js";
|
import {Permissions} from "./permissions.js";
|
||||||
import {Localuser} from "./localuser.js";
|
import {Localuser} from "./localuser.js";
|
||||||
import {Guild} from "./guild.js";
|
import {Guild} from "./guild.js";
|
||||||
|
import { SnowFlake } from "./snowflake.js";
|
||||||
class Role{
|
class Role{
|
||||||
permissions:Permissions;
|
permissions:Permissions;
|
||||||
owner:Guild;
|
owner:Guild;
|
||||||
color:number;
|
color:number;
|
||||||
id:string;
|
readonly id:SnowFlake<Role>;
|
||||||
name:string;
|
name:string;
|
||||||
info:Guild["info"];
|
info:Guild["info"];
|
||||||
hoist:boolean;
|
hoist:boolean;
|
||||||
|
@ -18,6 +19,10 @@ class Role{
|
||||||
this.headers=owner.headers;
|
this.headers=owner.headers;
|
||||||
this.info=owner.info;
|
this.info=owner.info;
|
||||||
for(const thing of Object.keys(JSON)){
|
for(const thing of Object.keys(JSON)){
|
||||||
|
if(thing==="id"){
|
||||||
|
this.id=new SnowFlake(JSON.id,this);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
this[thing]=JSON[thing];
|
this[thing]=JSON[thing];
|
||||||
}
|
}
|
||||||
this.permissions=new Permissions(JSON.permissions);
|
this.permissions=new Permissions(JSON.permissions);
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import { Permissions } from "./permissions.js";
|
import { Permissions } from "./permissions.js";
|
||||||
import { Guild } from "./guild.js";
|
import { Guild } from "./guild.js";
|
||||||
|
import { SnowFlake } from "./snowflake.js";
|
||||||
|
import { Role } from "./role.js";
|
||||||
|
|
||||||
class Buttons{
|
class Buttons{
|
||||||
readonly name:string;
|
readonly name:string;
|
||||||
|
@ -126,7 +128,7 @@ class PermissionToggle{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class RoleList extends Buttons{
|
class RoleList extends Buttons{
|
||||||
readonly permissions:[string,Permissions][];
|
readonly permissions:[SnowFlake<Role>,Permissions][];
|
||||||
permission:Permissions;
|
permission:Permissions;
|
||||||
readonly guild:Guild;
|
readonly guild:Guild;
|
||||||
readonly channel:boolean;
|
readonly channel:boolean;
|
||||||
|
@ -134,7 +136,7 @@ class RoleList extends Buttons{
|
||||||
readonly options:Options;
|
readonly options:Options;
|
||||||
onchange:Function;
|
onchange:Function;
|
||||||
curid:string;
|
curid:string;
|
||||||
constructor(permissions:[string,Permissions][],guild:Guild,onchange:Function,channel=false){
|
constructor(permissions:[SnowFlake<Role>,Permissions][],guild:Guild,onchange:Function,channel=false){
|
||||||
super("Roles");
|
super("Roles");
|
||||||
this.guild=guild;
|
this.guild=guild;
|
||||||
this.permissions=permissions;
|
this.permissions=permissions;
|
||||||
|
@ -150,16 +152,17 @@ class RoleList extends Buttons{
|
||||||
options.addPermissionToggle(thing,this.permission);//
|
options.addPermissionToggle(thing,this.permission);//
|
||||||
}
|
}
|
||||||
for(const i of permissions){
|
for(const i of permissions){
|
||||||
this.buttons.push([guild.getRole(i[0]).name,i[0]])//
|
console.log(i);
|
||||||
|
this.buttons.push([i[0].getObject().name,i[0].id])//
|
||||||
}
|
}
|
||||||
this.options=options;
|
this.options=options;
|
||||||
}
|
}
|
||||||
handleString(str:string):HTMLElement{
|
handleString(str:string):HTMLElement{
|
||||||
this.curid=str;
|
this.curid=str;
|
||||||
const perm=this.permissions.find(_=>_[0]===str)[1];
|
const perm=this.permissions.find(_=>_[0].id===str)[1];
|
||||||
this.permission.deny=perm.deny;
|
this.permission.deny=perm.deny;
|
||||||
this.permission.allow=perm.allow;
|
this.permission.allow=perm.allow;
|
||||||
this.options.name=this.guild.getRole(str).name;
|
this.options.name=SnowFlake.getSnowFlakeFromID(str,Role).getObject().name;
|
||||||
this.options.haschanged=false;
|
this.options.haschanged=false;
|
||||||
return this.options.generateHTML();
|
return this.options.generateHTML();
|
||||||
}
|
}
|
||||||
|
|
53
webpage/snowflake.ts
Normal file
53
webpage/snowflake.ts
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
class SnowFlake<x>{
|
||||||
|
public readonly id:string;
|
||||||
|
private static readonly SnowFlakes:Map<any,Map<string,WeakRef<SnowFlake<any>>>>=new Map();
|
||||||
|
private static readonly FinalizationRegistry=new FinalizationRegistry((id:string)=>{
|
||||||
|
SnowFlake.SnowFlakes.delete(id);
|
||||||
|
});
|
||||||
|
private obj:x;
|
||||||
|
constructor(id:string,obj:x){
|
||||||
|
if(!obj){
|
||||||
|
this.id=id;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(!SnowFlake.SnowFlakes.get(obj.constructor)){
|
||||||
|
SnowFlake.SnowFlakes.set(obj.constructor,new Map());
|
||||||
|
}
|
||||||
|
if(SnowFlake.SnowFlakes.get(obj.constructor).get(id)){
|
||||||
|
const snowflake=SnowFlake.SnowFlakes.get(obj.constructor).get(id).deref();
|
||||||
|
snowflake.obj=obj;
|
||||||
|
return snowflake;
|
||||||
|
}
|
||||||
|
this.id=id;
|
||||||
|
SnowFlake.SnowFlakes.get(obj.constructor).set(id,new WeakRef(this));
|
||||||
|
SnowFlake.FinalizationRegistry.register(this,id);
|
||||||
|
this.obj=obj;
|
||||||
|
}
|
||||||
|
static getSnowFlakeFromID(id:string,type:any):SnowFlake<any>{
|
||||||
|
if(!SnowFlake.SnowFlakes.get(type)){
|
||||||
|
SnowFlake.SnowFlakes.set(type,new Map());
|
||||||
|
}
|
||||||
|
const snowflake=SnowFlake.SnowFlakes.get(type).get(id);
|
||||||
|
if(snowflake){
|
||||||
|
return snowflake.deref();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const snowflake=new SnowFlake(id,undefined);
|
||||||
|
|
||||||
|
SnowFlake.SnowFlakes.get(type).set(id,new WeakRef(snowflake));
|
||||||
|
SnowFlake.FinalizationRegistry.register(snowflake,id);
|
||||||
|
|
||||||
|
return snowflake;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getUnixTime():number{
|
||||||
|
return Number((BigInt(this.id)>>22n)+1420070400000n);
|
||||||
|
}
|
||||||
|
toString(){
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
getObject():x{
|
||||||
|
return this.obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export {SnowFlake};
|
|
@ -119,14 +119,17 @@ samp {
|
||||||
}
|
}
|
||||||
|
|
||||||
.infosection {
|
.infosection {
|
||||||
|
hr{
|
||||||
|
width:100%;
|
||||||
|
}
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
background: var(--profile-info-bg);
|
background: var(--profile-info-bg);
|
||||||
border-radius: 10%;
|
border-radius: 10%;
|
||||||
padding: .3cm;
|
padding: .3cm;
|
||||||
width: 100%;
|
width: calc(100% - .6cm);
|
||||||
height: calc(100% - .5in - .2cm);
|
height: calc(100% - .75in);
|
||||||
margin-top: .1cm;
|
display: flex;
|
||||||
box-sizing: border-box;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.profile {
|
.profile {
|
||||||
|
@ -152,6 +155,7 @@ h1,
|
||||||
h2,
|
h2,
|
||||||
h3 {
|
h3 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
|
@ -342,15 +346,16 @@ div {
|
||||||
|
|
||||||
#typebox {
|
#typebox {
|
||||||
font-family: "acumin-pro", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
font-family: "acumin-pro", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||||
font-size: 16px;
|
/* font-size: 16px; */
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
border-radius: .25cm;
|
border-radius: .25cm;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: .6in;
|
min-height: .5in;
|
||||||
z-index: -100;
|
z-index: -100;
|
||||||
display: flex;
|
display: flex;
|
||||||
max-height: fit-content;
|
max-height: fit-content;
|
||||||
box-sizing: border-box;
|
max-height: 1.5in;
|
||||||
|
overflow-y: scroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
|
@ -630,7 +635,11 @@ textarea {
|
||||||
textarea:focus-visible {
|
textarea:focus-visible {
|
||||||
outline: 2px solid var(--focus);
|
outline: 2px solid var(--focus);
|
||||||
}
|
}
|
||||||
|
#typebox{
|
||||||
|
color: var(--primary-text);
|
||||||
|
background: var(--textarea-bg);
|
||||||
|
border: 1px solid;
|
||||||
|
}
|
||||||
.channels {
|
.channels {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
transition: height .2s ease-in-out;
|
transition: height .2s ease-in-out;
|
||||||
|
@ -731,22 +740,20 @@ textarea:focus-visible {
|
||||||
flex-shrink: 1;
|
flex-shrink: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#settings {
|
#user-actions {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
#user-actions h2 {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
border-radius: .3in;
|
border-radius: .1in;
|
||||||
transition: background 1s;
|
transition: color .5s;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: .25in;
|
|
||||||
width: .3in;
|
|
||||||
height: .3in;
|
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
}
|
}
|
||||||
|
#user-actions h2:hover, #user-actions h2:focus {
|
||||||
#settings:hover {
|
color: var(--timestamp-color);
|
||||||
background: var(--settings-hover);
|
|
||||||
cursor: pointer;
|
|
||||||
user-select: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#userinfo {
|
#userinfo {
|
||||||
|
@ -1402,6 +1409,41 @@ span {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
max-height:100in;
|
max-height:100in;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#connection-container, #app-list-container {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 10px;
|
||||||
|
max-width: 700px;
|
||||||
|
}
|
||||||
|
#connection-container div, #app-list-container div {
|
||||||
|
padding: 5px 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
background-color: var(--textarea-bg);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
#connection-container .disabled {
|
||||||
|
background-color: var(--embed-fallback);
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
.sizeupdown{
|
.sizeupdown{
|
||||||
height:4in;
|
height:4in;
|
||||||
}
|
}
|
||||||
|
.bigemoji{
|
||||||
|
width:48px;
|
||||||
|
height:48px;
|
||||||
|
}
|
||||||
|
.smallemoji{
|
||||||
|
width:22px;
|
||||||
|
height:22px;
|
||||||
|
}
|
||||||
|
#typebox[contenteditable=false]{
|
||||||
|
|
||||||
|
cursor:not-allowed;
|
||||||
|
|
||||||
|
}
|
||||||
|
#typebox[contenteditable=false]:before{
|
||||||
|
content:'You can\'t chat here';
|
||||||
|
color:color-mix(in hsl, var(--primary-bg),var(--primary-text));
|
||||||
|
}
|
|
@ -1,31 +1,32 @@
|
||||||
//const usercache={};
|
//const usercache={};
|
||||||
import {Member} from "./member.js";
|
import {Member} from "./member.js";
|
||||||
import {markdown} from "./markdown.js";
|
import {MarkDown} from "./markdown.js";
|
||||||
import {Contextmenu} from "./contextmenu.js";
|
import {Contextmenu} from "./contextmenu.js";
|
||||||
import {Localuser} from "./localuser.js";
|
import {Localuser} from "./localuser.js";
|
||||||
import {Guild} from "./guild.js";
|
import {Guild} from "./guild.js";
|
||||||
|
import { SnowFlake } from "./snowflake.js";
|
||||||
|
|
||||||
class User{
|
class User{
|
||||||
static userids={};
|
static userids={};
|
||||||
owner:Localuser;
|
owner:Localuser;
|
||||||
hypotheticalpfp:boolean;
|
hypotheticalpfp:boolean;
|
||||||
id:string;
|
id:SnowFlake<User>;
|
||||||
avatar:string;
|
avatar:string;
|
||||||
username:string;
|
username:string;
|
||||||
bio:string;
|
bio:MarkDown;
|
||||||
discriminator:string;
|
discriminator:string;
|
||||||
pronouns:string;
|
pronouns:string;
|
||||||
bot:boolean;
|
bot:boolean;
|
||||||
static contextmenu:Contextmenu=new Contextmenu("User Menu");
|
static contextmenu:Contextmenu=new Contextmenu("User Menu");
|
||||||
static setUpContextMenu(){
|
static setUpContextMenu(){
|
||||||
this.contextmenu.addbutton("Copy user id",function(){
|
this.contextmenu.addbutton("Copy user id",function(){
|
||||||
navigator.clipboard.writeText(this.id);
|
navigator.clipboard.writeText(this.id.id);
|
||||||
});
|
});
|
||||||
this.contextmenu.addbutton("Message user",function(){
|
this.contextmenu.addbutton("Message user",function(){
|
||||||
fetch(this.info.api.toString()+"/v9/users/@me/channels",
|
fetch(this.info.api.toString()+"/v9/users/@me/channels",
|
||||||
{method:"POST",
|
{method:"POST",
|
||||||
body:JSON.stringify({"recipients":[this.id]}),
|
body:JSON.stringify({"recipients":[this.id.id]}),
|
||||||
headers: this.headers
|
headers: this.localuser.headers
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -49,6 +50,14 @@ class User{
|
||||||
if(!owner){console.error("missing localuser")}
|
if(!owner){console.error("missing localuser")}
|
||||||
if(dontclone){
|
if(dontclone){
|
||||||
for(const thing of Object.keys(userjson)){
|
for(const thing of Object.keys(userjson)){
|
||||||
|
if(thing==="bio"){
|
||||||
|
this.bio=new MarkDown(userjson[thing],this.localuser);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(thing === "id"){
|
||||||
|
this.id=new SnowFlake(userjson[thing],this);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
this[thing]=userjson[thing];
|
this[thing]=userjson[thing];
|
||||||
}
|
}
|
||||||
this.hypotheticalpfp=false;
|
this.hypotheticalpfp=false;
|
||||||
|
@ -63,7 +72,7 @@ class User{
|
||||||
const pfp=document.createElement('img');
|
const pfp=document.createElement('img');
|
||||||
pfp.src=this.getpfpsrc();
|
pfp.src=this.getpfpsrc();
|
||||||
pfp.classList.add("pfp");
|
pfp.classList.add("pfp");
|
||||||
pfp.classList.add("userid:"+this.id);
|
pfp.classList.add("userid:"+this.id.id);
|
||||||
return pfp;
|
return pfp;
|
||||||
}
|
}
|
||||||
userupdate(json){
|
userupdate(json){
|
||||||
|
@ -73,7 +82,7 @@ class User{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bind(html:HTMLElement,guild:Guild=null){
|
bind(html:HTMLElement,guild:Guild=null){
|
||||||
if(guild&&guild.id!=="@me"){
|
if(guild&&guild.id.id!=="@me"){
|
||||||
Member.resolve(this,guild).then(_=>{
|
Member.resolve(this,guild).then(_=>{
|
||||||
_.bind(html);
|
_.bind(html);
|
||||||
}).catch(_=>{
|
}).catch(_=>{
|
||||||
|
@ -94,7 +103,7 @@ class User{
|
||||||
this.hypotheticalpfp=false;
|
this.hypotheticalpfp=false;
|
||||||
const src=this.getpfpsrc();
|
const src=this.getpfpsrc();
|
||||||
console.log(src)
|
console.log(src)
|
||||||
for(const thing of document.getElementsByClassName("userid:"+this.id)){
|
for(const thing of document.getElementsByClassName("userid:"+this.id.id)){
|
||||||
(thing as HTMLImageElement).src=src;
|
(thing as HTMLImageElement).src=src;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,7 +112,7 @@ class User{
|
||||||
return this.avatar;
|
return this.avatar;
|
||||||
}
|
}
|
||||||
if(this.avatar!=null){
|
if(this.avatar!=null){
|
||||||
return this.info.cdn.toString()+"avatars/"+this.id+"/"+this.avatar+".png";
|
return this.info.cdn.toString()+"avatars/"+this.id.id+"/"+this.avatar+".png";
|
||||||
}else{
|
}else{
|
||||||
return this.info.cdn.toString()+"embed/avatars/3.png";
|
return this.info.cdn.toString()+"embed/avatars/3.png";
|
||||||
}
|
}
|
||||||
|
@ -152,7 +161,7 @@ class User{
|
||||||
|
|
||||||
const rule=document.createElement("hr");
|
const rule=document.createElement("hr");
|
||||||
userbody.appendChild(rule);
|
userbody.appendChild(rule);
|
||||||
const biohtml=markdown(this.bio);
|
const biohtml=this.bio.makeHTML();
|
||||||
userbody.appendChild(biohtml);
|
userbody.appendChild(biohtml);
|
||||||
}
|
}
|
||||||
console.log(div);
|
console.log(div);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue