Correcting names, and deleting message

There is a known regresion for the MESSAGE_CREATE event while it's not on screen, though I have not been able to replicate it while I'm looking for it. If you see this bug, please let me know the conditions it happens under
This commit is contained in:
MathMan05 2024-06-28 11:13:26 -05:00
parent 845c7f6612
commit ac939e5fb6
17 changed files with 473 additions and 166 deletions

View file

@ -31,6 +31,7 @@ class Channel {
message_notifications;
allthewayup;
static contextmenu = new Contextmenu("channel menu");
replyingto;
static setupcontextmenu() {
Channel.contextmenu.addbutton("Copy channel id", function () {
console.log(this);
@ -68,7 +69,6 @@ class Channel {
for (const thing of JSON.permission_overwrites) {
this.permission_overwrites[thing.id] = new Permissions(thing.allow, thing.deny);
}
console.log(this.permission_overwrites);
this.topic = JSON.topic;
this.nsfw = JSON.nsfw;
this.position = JSON.position;
@ -94,21 +94,31 @@ class Channel {
this.lastpin = json.last_pin_timestamp;
}
get hasunreads() {
return this.lastmessageid !== this.lastreadmessageid && this.type !== 4;
}
get canMessage() {
console.log("this should run");
for (const thing of Object.entries(this.permission_overwrites)) {
const perm = thing[1].getPermision("SEND_MESSAGES");
if (perm === 1) {
return true;
}
if (perm === -1) {
if (!this.hasPermission("VIEW_CHANNEL")) {
return false;
}
return this.lastmessageid !== this.lastreadmessageid && this.type !== 4;
}
hasPermission(name, member = this.guild.member) {
if (member.isAdmin()) {
return true;
}
for (const thing of member.roles) {
if (this.permission_overwrites[thing.id]) {
let perm = this.permission_overwrites[thing.id].getPermision(name);
if (perm) {
return perm === 1;
}
}
if (thing.permissions.getPermision(name)) {
return true;
}
}
return false;
}
get canMessage() {
return this.hasPermission("SEND_MESSAGES");
}
sortchildren() {
this.children.sort((a, b) => { return a.position - b.position; });
}
@ -144,6 +154,17 @@ class Channel {
static dragged = [];
createguildHTML(admin = false) {
const div = document.createElement("div");
if (!this.hasPermission("VIEW_CHANNEL")) {
let quit = true;
for (const thing of this.children) {
if (thing.hasPermission("VIEW_CHANNEL")) {
quit = false;
}
}
if (quit) {
return div;
}
}
div["all"] = this;
div.draggable = admin;
div.addEventListener("dragstart", (e) => { Channel.dragged = [this, div]; e.stopImmediatePropagation(); });
@ -383,34 +404,38 @@ class Channel {
headers: this.headers
});
}
getHTML() {
async getHTML() {
if (this.guild !== this.localuser.lookingguild) {
this.guild.loadGuild();
}
this.guild.prevchannel = this;
this.localuser.channelfocus = this;
this.putmessages();
const prom = Message.wipeChanel();
await this.putmessages();
await prom;
this.buildmessages();
history.pushState(null, null, "/channels/" + this.guild_id + "/" + this.id);
document.getElementById("channelname").textContent = "#" + this.name;
console.log(this);
document.getElementById("typebox").disabled = !this.canMessage;
}
putmessages() {
const out = this;
fetch(this.info.api.toString() + "/channels/" + this.id + "/messages?limit=100", {
async putmessages() {
if (this.messages.length >= 100) {
return;
}
;
const j = await fetch(this.info.api.toString() + "/channels/" + this.id + "/messages?limit=100", {
method: 'GET',
headers: this.headers,
}).then((j) => { return j.json(); }).then(responce => {
document.getElementById("messages").innerHTML = '';
});
const responce = await j.json();
for (const thing of responce) {
const messager = new Message(thing, this);
if (out.messageids[messager.id] == undefined) {
out.messageids[messager.id] = messager;
out.messages.push(messager);
if (this.messageids[messager.id] === undefined) {
this.messageids[messager.id] = messager;
this.messages.push(messager);
}
}
out.buildmessages();
});
}
delChannel(JSON) {
const build = [];
@ -565,6 +590,9 @@ class Channel {
}
}
messageCreate(messagep) {
if (!this.hasPermission("VIEW_CHANNEL")) {
return;
}
const messagez = new Message(messagep.d, this);
this.lastmessageid = messagez.id;
if (messagez.author === this.localuser.user) {

View file

@ -52,11 +52,15 @@ class Contextmenu {
return this.div;
}
bind(obj, addinfo = undefined) {
obj.addEventListener("contextmenu", (event) => {
const func = (event) => {
event.preventDefault();
event.stopImmediatePropagation();
this.makemenu(event.clientX, event.clientY, addinfo, obj);
});
};
obj.addEventListener("contextmenu", func);
return func;
}
static keepOnScreen(obj) {
}
}
Contextmenu.setup();

View file

@ -4,7 +4,7 @@ import { Message } from "./message.js";
import { User } from "./user.js";
class Direct extends Guild {
constructor(JSON, owner) {
super(-1, owner);
super(-1, owner, null);
this.message_notifications = 0;
console.log(JSON);
this.owner = owner;
@ -97,10 +97,16 @@ class Group extends Channel {
};
return div;
}
getHTML() {
async getHTML() {
if (this.guild !== this.localuser.lookingguild) {
this.guild.loadGuild();
}
const prom = Message.wipeChanel();
this.guild.prevchannel = this;
this.localuser.channelfocus = this;
this.putmessages();
await this.putmessages();
await prom;
this.buildmessages();
history.pushState(null, null, "/channels/" + this.guild_id + "/" + this.id);
document.getElementById("channelname").textContent = "@" + this.name;
}
@ -186,5 +192,11 @@ class Group extends Channel {
else {
}
}
isAdmin() {
return false;
}
hasPermission(name, member) {
return true;
}
}
export { Direct, Group };

View file

@ -2,6 +2,7 @@ import { Channel } from "./channel.js";
import { Contextmenu } from "./contextmenu.js";
import { Role } from "./role.js";
import { Fullscreen } from "./fullscreen.js";
import { Member } from "./member.js";
class Guild {
owner;
headers;
@ -52,15 +53,12 @@ class Guild {
},null,_=>{return thisuser.isAdmin()})
*/
}
constructor(JSON, owner) {
constructor(JSON, owner, member) {
if (JSON === -1) {
return;
}
this.owner = owner;
this.headers = this.owner.headers;
if (!this.owner) {
console.error("localuser was not included, please fix");
}
this.channels = [];
this.channelids = {};
this.id = JSON.id;
@ -74,6 +72,7 @@ class Guild {
this.roles.push(roleh);
this.roleids[roleh.id] = roleh;
}
Member.resolve(member, this).then(_ => this.member = _);
for (const thing of JSON.channels) {
const temp = new Channel(thing, this);
this.channels.push(temp);
@ -353,19 +352,10 @@ class Guild {
body: JSON.stringify(build)
});
}
fillMember(member) {
const realroles = [];
for (const thing of member.roles) {
realroles.push(this.getRole(thing));
}
member.roles = realroles;
return member;
}
giveMember(member) {
this.fillMember(member);
this.member = member;
}
getRole(ID) {
if (!this.roleids[ID]) {
console.error(`role id ${ID} does not exist`, this.roleids);
}
return this.roleids[ID];
}
hasRole(r) {

View file

@ -128,11 +128,12 @@ async function enter(event) {
channel.editing = null;
}
else {
replyingto = thisuser.channelfocus.replyingto;
let replying = replyingto?.all;
if (replyingto) {
replyingto.classList.remove("replying");
}
replyingto = false;
thisuser.channelfocus.replyingto = null;
channel.sendMessage(typebox.value, {
attachments: images,
replyingto: replying,

View file

@ -2,7 +2,6 @@ import { Guild } from "./guild.js";
import { Direct } from "./direct.js";
import { Voice } from "./audio.js";
import { User } from "./user.js";
import { Member } from "./member.js";
import { markdown } from "./markdown.js";
import { Fullscreen } from "./fullscreen.js";
import { setTheme } from "./login.js";
@ -48,8 +47,12 @@ class Localuser {
this.channelfocus = null;
this.lookingguild = null;
this.guildhtml = {};
const members = {};
for (const thing of ready.d.merged_members) {
members[thing[0].guild_id] = thing[0];
}
for (const thing of ready.d.guilds) {
const temp = new Guild(thing, this);
const temp = new Guild(thing, this, members[thing.id]);
this.guilds.push(temp);
this.guildids[temp.id] = temp;
}
@ -62,11 +65,6 @@ class Localuser {
for (const thing of ready.d.user_guild_settings.entries) {
this.guildids[thing.guild_id].notisetting(thing);
}
for (const thing of ready.d.merged_members) {
const guild = this.guildids[thing[0].guild_id];
const temp = new Member(thing[0], guild);
guild.giveMember(temp);
}
for (const thing of ready.d.read_state.entries) {
const guild = this.resolveChannelFromID(thing.id).guild;
if (guild === undefined) {
@ -130,6 +128,10 @@ class Localuser {
this.messageCreate(temp);
}
break;
case "MESSAGE_DELETE":
console.log(temp.d);
this.guildids[temp.d.guild_id].channelids[temp.d.channel_id].messageids[temp.d.id].deleteEvent();
break;
case "READY":
this.gottenReady(temp);
this.genusersettings();
@ -193,7 +195,7 @@ class Localuser {
}
case "GUILD_CREATE":
{
const guildy = new Guild(temp.d, this);
const guildy = new Guild(temp.d, this, this.user);
this.guilds.push(guildy);
this.guildids[guildy.id] = guildy;
document.getElementById("servers").insertBefore(guildy.generateGuildIcon(), document.getElementById("bottomseperator"));
@ -236,7 +238,6 @@ class Localuser {
return;
}
resolveChannelFromID(ID) {
console.log(this.guilds.find(guild => guild.channelids[ID]).channelids);
let resolve = this.guilds.find(guild => guild.channelids[ID]).channelids[ID];
resolve ??= undefined;
return resolve;

View file

@ -1,27 +1,45 @@
import { User } from "./user.js";
import { Guild } from "./guild.js";
class Member {
static already = {};
owner;
user;
roles;
constructor(memberjson, owner) {
if (!owner) {
console.error("Guild not included in the creation of a member object");
}
error;
constructor(memberjson, owner, error = false) {
this.error = error;
this.owner = owner;
let membery = memberjson;
this.roles = [];
if (!error) {
if (memberjson.guild_member) {
membery = memberjson.guild_member;
this.user = memberjson.user;
}
}
for (const thing of Object.keys(membery)) {
if (thing === "guild") {
continue;
}
if (thing === "owner") {
continue;
}
if (thing === "roles") {
for (const strrole of membery["roles"]) {
const role = this.guild.getRole(strrole);
this.roles.push(role);
}
continue;
}
this[thing] = membery[thing];
}
if (error) {
this.user = memberjson;
}
else {
this.user = new User(this.user, owner.localuser);
}
}
get guild() {
return this.owner;
}
@ -31,7 +49,17 @@ class Member {
get info() {
return this.owner.info;
}
static async resolve(user, guild) {
static async resolve(unkown, guild) {
if (!(guild instanceof Guild)) {
console.error(guild);
}
let user;
if (unkown instanceof User) {
user = unkown;
}
else {
return new Member(unkown, guild);
}
if (guild.id === "@me") {
return null;
}
@ -48,13 +76,19 @@ class Member {
const promoise = fetch(guild.info.api.toString() + "/v9/users/" + user.id + "/profile?with_mutual_guilds=true&with_mutual_friends_count=true&guild_id=" + guild.id, { headers: guild.headers }).then(_ => _.json()).then(json => {
const memb = new Member(json, guild);
Member.already[guild.id][user.id] = memb;
guild.fillMember(memb);
console.log("resolved");
return memb;
});
Member.already[guild.id][user.id] = promoise;
try {
return await promoise;
}
catch (_) {
const memb = new Member(user, guild, true);
Member.already[guild.id][user.id] = memb;
return memb;
}
}
hasRole(ID) {
console.log(this.roles, ID);
for (const thing of this.roles) {
@ -74,6 +108,11 @@ class Member {
return "";
}
isAdmin() {
for (const role of this.roles) {
if (role.permissions.getPermision("ADMINISTRATOR")) {
return true;
}
}
return this.guild.properties.owner_id === this.user.id;
}
}

View file

@ -12,12 +12,25 @@ class Message {
author;
mentions;
mention_roles;
attachments;
attachments; //probably should be its own class tbh, should be Attachments[]
id;
message_reference;
type;
timestamp;
content;
static del;
static resolve;
div;
static setup() {
this.del = new Promise(_ => { this.resolve = _; });
Message.setupcmenu();
}
static async wipeChanel() {
this.resolve();
document.getElementById("messages").innerHTML = "";
await Promise.allSettled([this.resolve]);
this.del = new Promise(_ => { this.resolve = _; });
}
static setupcmenu() {
Message.contextmenu.addbutton("Copy raw text", function () {
navigator.clipboard.writeText(this.content);
@ -46,6 +59,9 @@ class Message {
this.channel.editing = this;
document.getElementById("typebox").value = this.content;
}, null, _ => { return _.author.id === _.localuser.user.id; });
Message.contextmenu.addbutton("Delete message", function () {
this.delete();
}, null, _ => { return _.canDelete(); });
}
constructor(messagejson, owner) {
this.owner = owner;
@ -68,6 +84,9 @@ class Message {
console.log(this);
}
}
canDelete() {
return this.channel.hasPermission("MANAGE_MESSAGES") || this.author.id === this.localuser.user.id;
}
get channel() {
return this.owner;
}
@ -81,7 +100,12 @@ class Message {
return this.owner.info;
}
messageevents(obj) {
Message.contextmenu.bind(obj, this);
const func = Message.contextmenu.bind(obj, this);
this.div = obj;
Message.del.then(_ => {
obj.removeEventListener("click", func);
this.div = null;
});
obj.classList.add("messagediv");
}
mentionsuser(userd) {
@ -108,10 +132,32 @@ class Message {
body: JSON.stringify({ content: content })
});
}
buildhtml(premessage) {
//premessage??=messages.lastChild;
delete() {
fetch(`${this.info.api.toString()}/channels/${this.channel.id}/messages/${this.id}`, {
headers: this.headers,
method: "DELETE",
});
}
deleteEvent() {
if (this.div) {
this.div.innerHTML = "";
this.div = null;
}
const index = this.channel.messages.indexOf(this);
this.channel.messages.splice(this.channel.messages.indexOf(this), 1);
delete this.channel.messageids[this.id];
const regen = this.channel.messages[index - 1];
if (regen) {
regen.generateMessage();
}
}
generateMessage(premessage = null) {
if (!premessage) {
premessage = this.channel.messages[this.channel.messages.indexOf(this) + 1];
}
const div = this.div;
div.innerHTML = "";
const build = document.createElement('table');
const div = document.createElement("div");
if (this.message_reference) {
const replyline = document.createElement("div");
const line = document.createElement("hr");
@ -124,7 +170,23 @@ class Message {
const reply = document.createElement("div");
username.classList.add("username");
Member.resolve(this.author, this.guild).then(_ => {
if (!_) {
return;
}
;
console.log(_.error);
if (_.error) {
username.textContent += "Error";
alert("Should've gotten here");
const error = document.createElement("span");
error.textContent = "!";
error.classList.add("membererror");
username.after(error);
return;
}
username.style.color = _.getColor();
}).catch(_ => {
console.log(_);
});
reply.classList.add("replytext");
replyline.appendChild(reply);
@ -150,7 +212,6 @@ class Message {
const pfpRow = document.createElement('th');
let pfpparent, current;
if (premessage != null) {
pfpparent = premessage.pfpparent;
pfpparent ??= premessage;
let pfpparent2 = pfpparent.all;
pfpparent2 ??= pfpparent;
@ -158,7 +219,7 @@ class Message {
const newt = (new Date(this.timestamp).getTime()) / 1000;
current = (newt - old) > 600;
}
const combine = (premessage?.userid != this.author.id && premessage?.author?.id != this.author.id) || (current) || this.message_reference;
const combine = (premessage?.author?.id != this.author.id) || (current) || this.message_reference;
if (combine) {
const pfp = this.author.buildpfp();
this.author.profileclick(pfp);
@ -181,6 +242,14 @@ class Message {
if (!_) {
return;
}
;
if (_.error) {
const error = document.createElement("span");
error.textContent = "!";
error.classList.add("membererror");
username.after(error);
return;
}
username.style.color = _.getColor();
});
username.textContent = this.author.username;
@ -254,10 +323,19 @@ class Message {
messagedwrap.append(time);
texttxt.appendChild(messagedwrap);
}
div["userid"] = this.author.id;
div["all"] = this;
return (div);
}
buildhtml(premessage) {
if (this.div) {
console.error(`HTML for ${this} already exists, aborting`);
return;
}
//premessage??=messages.lastChild;
const div = document.createElement("div");
this.div = div;
return this.generateMessage(premessage);
}
createunknown(fname, fsize, src) {
const div = document.createElement("table");
div.classList.add("unknownfile");
@ -314,5 +392,5 @@ function formatTime(date) {
return `${date.toLocaleDateString()} at ${formatTime(date)}`;
}
}
Message.setupcmenu();
Message.setup();
export { Message };

View file

@ -7,6 +7,7 @@ import {markdown} from "./markdown.js";
import {Guild} from "./guild.js";
import { Localuser } from "./localuser.js";
import { Permissions } from "./permissions.js";
declare global {
interface NotificationOptions {
image?: string
@ -38,6 +39,7 @@ class Channel{
message_notifications:number;
allthewayup:boolean;
static contextmenu=new Contextmenu("channel menu");
replyingto:HTMLDivElement;
static setupcontextmenu(){
Channel.contextmenu.addbutton("Copy channel id",function(){
console.log(this)
@ -79,7 +81,6 @@ class Channel{
for(const thing of JSON.permission_overwrites){
this.permission_overwrites[thing.id]=new Permissions(thing.allow,thing.deny);
}
console.log(this.permission_overwrites)
this.topic=JSON.topic;
this.nsfw=JSON.nsfw;
this.position=JSON.position;
@ -104,21 +105,29 @@ class Channel{
this.mentions??=0;
this.lastpin=json.last_pin_timestamp;
}
get hasunreads(){
get hasunreads():boolean{
if(!this.hasPermission("VIEW_CHANNEL")){return false;}
return this.lastmessageid!==this.lastreadmessageid&&this.type!==4;
}
get canMessage(){
console.log("this should run");
for(const thing of Object.entries(this.permission_overwrites)){
const perm=thing[1].getPermision("SEND_MESSAGES");
if(perm===1){
return true
hasPermission(name:string,member=this.guild.member):boolean{
if(member.isAdmin()){
return true;
}
for(const thing of member.roles){
if(this.permission_overwrites[thing.id]){
let perm=this.permission_overwrites[thing.id].getPermision(name);
if(perm){
return perm===1;
}
}
if(thing.permissions.getPermision(name)){
return true;
}
}
if(perm===-1){
return false;
}
}
return true;
get canMessage():boolean{
return this.hasPermission("SEND_MESSAGES");
}
sortchildren(){
this.children.sort((a,b)=>{return a.position-b.position});
@ -153,8 +162,19 @@ class Channel{
return build;
}
static dragged=[];
createguildHTML(admin=false){
createguildHTML(admin=false):HTMLDivElement{
const div=document.createElement("div");
if(!this.hasPermission("VIEW_CHANNEL")){
let quit=true
for(const thing of this.children){
if(thing.hasPermission("VIEW_CHANNEL")){
quit=false;
}
}
if(quit){
return div;
}
}
div["all"]=this;
div.draggable=admin;
div.addEventListener("dragstart",(e)=>{Channel.dragged=[this,div];e.stopImmediatePropagation()})
@ -392,34 +412,35 @@ class Channel{
headers:this.headers
})
}
getHTML(){
async getHTML(){
if(this.guild!==this.localuser.lookingguild){
this.guild.loadGuild();
}
this.guild.prevchannel=this;
this.localuser.channelfocus=this;
this.putmessages();
const prom=Message.wipeChanel();
await this.putmessages();
await prom;
this.buildmessages();
history.pushState(null, null,"/channels/"+this.guild_id+"/"+this.id);
document.getElementById("channelname").textContent="#"+this.name;
console.log(this);
(document.getElementById("typebox") as HTMLInputElement).disabled=!this.canMessage;
}
putmessages(){
const out=this;
fetch(this.info.api.toString()+"/channels/"+this.id+"/messages?limit=100",{
async putmessages(){
if(this.messages.length>=100){return};
const j=await fetch(this.info.api.toString()+"/channels/"+this.id+"/messages?limit=100",{
method: 'GET',
headers: this.headers,
}).then((j)=>{return j.json()}).then(responce=>{
document.getElementById("messages").innerHTML = '';
})
const responce=await j.json();
for(const thing of responce){
const messager=new Message(thing,this)
if(out.messageids[messager.id]==undefined){
out.messageids[messager.id]=messager;
out.messages.push(messager);
if(this.messageids[messager.id]===undefined){
this.messageids[messager.id]=messager;
this.messages.push(messager);
}
}
out.buildmessages();
})
}
delChannel(JSON){
const build=[];
@ -569,6 +590,7 @@ class Channel{
}
}
messageCreate(messagep:any):void{
if(!this.hasPermission("VIEW_CHANNEL")){return}
const messagez=new Message(messagep.d,this);
this.lastmessageid=messagez.id;
if(messagez.author===this.localuser.user){

View file

@ -50,11 +50,16 @@ class Contextmenu{
return this.div;
}
bind(obj:HTMLElement,addinfo:any=undefined){
obj.addEventListener("contextmenu", (event) => {
const func=(event) => {
event.preventDefault();
event.stopImmediatePropagation();
this.makemenu(event.clientX,event.clientY,addinfo,obj)
});
}
obj.addEventListener("contextmenu", func);
return func;
}
static keepOnScreen(obj:HTMLElement){
}
}
Contextmenu.setup();

View file

@ -3,10 +3,11 @@ import { Channel } from "./channel.js";
import { Message } from "./message.js";
import { Localuser } from "./localuser.js";
import {User} from "./user.js";
import { Member } from "./member.js";
class Direct extends Guild{
constructor(JSON,owner:Localuser){
super(-1,owner);
super(-1,owner,null);
this.message_notifications=0;
console.log(JSON);
this.owner=owner;
@ -98,10 +99,16 @@ class Group extends Channel{
}
return div;
}
getHTML(){
async getHTML(){
if(this.guild!==this.localuser.lookingguild){
this.guild.loadGuild();
}
const prom=Message.wipeChanel();
this.guild.prevchannel=this;
this.localuser.channelfocus=this;
this.putmessages();
await this.putmessages();
await prom;
this.buildmessages();
history.pushState(null, null,"/channels/"+this.guild_id+"/"+this.id);
document.getElementById("channelname").textContent="@"+this.name;
}
@ -183,5 +190,11 @@ class Group extends Channel{
}
}
isAdmin(): boolean {
return false;
}
hasPermission(name: string, member?: Member): boolean {
return true;
}
}
export {Direct, Group};

View file

@ -15,7 +15,7 @@ class Guild{
roles:Role[];
roleids:{[key:string]:Role};
prevchannel:Channel;
message_notifications
message_notifications:number;
headchannels:Channel[];
position:number;
parent_id:string;
@ -60,16 +60,13 @@ class Guild{
},null,_=>{return thisuser.isAdmin()})
*/
}
constructor(JSON,owner:Localuser){
constructor(JSON,owner:Localuser,member){
if(JSON===-1){
return;
}
this.owner=owner;
this.headers=this.owner.headers;
if(!this.owner){
console.error("localuser was not included, please fix")
}
this.channels=[];
this.channelids={};
this.id=JSON.id;
@ -83,6 +80,7 @@ class Guild{
this.roles.push(roleh)
this.roleids[roleh.id]=roleh;
}
Member.resolve(member,this).then(_=>this.member=_);
for(const thing of JSON.channels){
const temp=new Channel(thing,this);
this.channels.push(temp);
@ -360,19 +358,8 @@ class Guild{
body:JSON.stringify(build)
})
}
fillMember(member:Member){
const realroles=[];
for(const thing of member.roles){
realroles.push(this.getRole(thing));
}
member.roles=realroles;
return member;
}
giveMember(member:Member){
this.fillMember(member);
this.member=member;
}
getRole(ID){
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){
@ -382,7 +369,7 @@ class Guild{
}
return this.member.hasRole(r as string);
}
loadChannel(ID=undefined){
loadChannel(ID:string=undefined){
if(ID&&this.channelids[ID]){
this.channelids[ID].getHTML();
return;

View file

@ -142,11 +142,12 @@ async function enter(event){
channel.editing.edit((typebox).value);
channel.editing=null;
}else{
replyingto= thisuser.channelfocus.replyingto;
let replying=replyingto?.all;
if(replyingto){
replyingto.classList.remove("replying");
}
replyingto=false;
thisuser.channelfocus.replyingto=null;
channel.sendMessage(typebox.value,{
attachments:images,
replyingto:replying,

View file

@ -49,8 +49,13 @@ class Localuser{
this.channelfocus=null;
this.lookingguild=null;
this.guildhtml={};
const members={};
for(const thing of ready.d.merged_members){
members[thing[0].guild_id]=thing[0];
}
for(const thing of ready.d.guilds){
const temp=new Guild(thing,this);
const temp=new Guild(thing,this,members[thing.id]);
this.guilds.push(temp);
this.guildids[temp.id]=temp;
}
@ -59,15 +64,13 @@ class Localuser{
this.guilds.push(temp);
this.guildids[temp.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){
this.guildids[thing.guild_id].notisetting(thing);
}
for(const thing of ready.d.merged_members){
const guild=this.guildids[thing[0].guild_id]
const temp=new Member(thing[0],guild);
guild.giveMember(temp);
}
for(const thing of ready.d.read_state.entries){
const guild=this.resolveChannelFromID(thing.id).guild;
if(guild===undefined){
@ -134,6 +137,10 @@ class Localuser{
this.messageCreate(temp);
}
break;
case "MESSAGE_DELETE":
console.log(temp.d);
this.guildids[temp.d.guild_id].channelids[temp.d.channel_id].messageids[temp.d.id].deleteEvent();
break;
case "READY":
this.gottenReady(temp);
this.genusersettings();
@ -196,7 +203,7 @@ class Localuser{
}
case "GUILD_CREATE":
{
const guildy=new Guild(temp.d,this);
const guildy=new Guild(temp.d,this,this.user);
this.guilds.push(guildy);
this.guildids[guildy.id]=guildy;
document.getElementById("servers").insertBefore(guildy.generateGuildIcon(),document.getElementById("bottomseperator"));
@ -239,7 +246,6 @@ class Localuser{
return;
}
resolveChannelFromID(ID:string):Channel{
console.log(this.guilds.find(guild => guild.channelids[ID]).channelids)
let resolve=this.guilds.find(guild => guild.channelids[ID]).channelids[ID];
resolve??=undefined;
return resolve;

View file

@ -6,20 +6,36 @@ class Member{
owner:Guild;
user:User;
roles:Role[];
constructor(memberjson,owner:Guild){
if(!owner){console.error("Guild not included in the creation of a member object")}
error:boolean;
constructor(memberjson,owner:Guild,error=false){
this.error=error;
this.owner=owner;
let membery=memberjson;
this.roles=[];
if(!error){
if(memberjson.guild_member){
membery=memberjson.guild_member;
this.user=memberjson.user;
}
}
for(const thing of Object.keys(membery)){
if(thing==="guild"){continue}
if(thing==="owner"){continue}
if(thing==="roles"){
for(const strrole of membery["roles"]){
const role=this.guild.getRole(strrole);
this.roles.push(role);
}
continue;
}
this[thing]=membery[thing];
}
if(error){
this.user=memberjson as User;
}else{
this.user=new User(this.user,owner.localuser);
}
}
get guild(){
return this.owner;
}
@ -29,7 +45,16 @@ class Member{
get info(){
return this.owner.info;
}
static async resolve(user:User,guild:Guild){
static async resolve(unkown:User|object,guild:Guild):Promise<Member>{
if(!(guild instanceof Guild)){
console.error(guild)
}
let user:User;
if(unkown instanceof User){
user=unkown as User;
}else{
return new Member(unkown,guild);
}
if(guild.id==="@me"){return null}
if(!Member.already[guild.id]){
Member.already[guild.id]={};
@ -43,12 +68,17 @@ class Member{
const promoise= fetch(guild.info.api.toString()+"/v9/users/"+user.id+"/profile?with_mutual_guilds=true&with_mutual_friends_count=true&guild_id="+guild.id,{headers:guild.headers}).then(_=>_.json()).then(json=>{
const memb=new Member(json,guild);
Member.already[guild.id][user.id]=memb;
guild.fillMember(memb);
console.log("resolved")
return memb
});
})
Member.already[guild.id][user.id]=promoise;
return await promoise;
try{
return await promoise
}catch(_){
const memb=new Member(user,guild,true);
Member.already[guild.id][user.id]=memb;
return memb;
}
}
hasRole(ID:string){
console.log(this.roles,ID);
@ -69,6 +99,11 @@ class Member{
return "";
}
isAdmin(){
for(const role of this.roles){
if(role.permissions.getPermision("ADMINISTRATOR")){
return true;
}
}
return this.guild.properties.owner_id===this.user.id;
}

View file

@ -16,12 +16,25 @@ class Message{
author:User;
mentions:User[];
mention_roles:Role[];
attachments;
attachments;//probably should be its own class tbh, should be Attachments[]
id:string;
message_reference;
type:number;
timestamp:number;
content;
content:string;
static del:Promise<void>;
static resolve:Function;
div:HTMLDivElement;
static setup(){
this.del=new Promise(_=>{this.resolve=_});
Message.setupcmenu();
}
static async wipeChanel(){
this.resolve();
document.getElementById("messages").innerHTML="";
await Promise.allSettled([this.resolve]);
this.del=new Promise(_=>{this.resolve=_})
}
static setupcmenu(){
Message.contextmenu.addbutton("Copy raw text",function(){
navigator.clipboard.writeText(this.content);
@ -51,8 +64,11 @@ class Message{
this.channel.editing=this;
(document.getElementById("typebox") as HTMLInputElement).value=this.content;
},null,_=>{return _.author.id===_.localuser.user.id});
Message.contextmenu.addbutton("Delete message",function(){
this.delete();
},null,_=>{return _.canDelete()})
}
constructor(messagejson,owner){
constructor(messagejson,owner:Channel){
this.owner=owner;
this.headers=this.owner.headers;
for(const thing of Object.keys(messagejson)){
@ -73,6 +89,9 @@ class Message{
console.log(this);
}
}
canDelete(){
return this.channel.hasPermission("MANAGE_MESSAGES")||this.author.id===this.localuser.user.id;
}
get channel(){
return this.owner;
}
@ -85,11 +104,16 @@ class Message{
get info(){
return this.owner.info;
}
messageevents(obj){
Message.contextmenu.bind(obj,this)
obj.classList.add("messagediv")
messageevents(obj:HTMLDivElement){
const func=Message.contextmenu.bind(obj,this);
this.div=obj;
Message.del.then(_=>{
obj.removeEventListener("click",func);
this.div=null;
})
obj.classList.add("messagediv");
}
mentionsuser(userd){
mentionsuser(userd:User|Member){
if(userd instanceof User){
return this.mentions.includes(userd);
}else if(userd instanceof Member){
@ -112,11 +136,32 @@ class Message{
body:JSON.stringify({content:content})
});
}
buildhtml(premessage){
//premessage??=messages.lastChild;
delete(){
fetch(`${this.info.api.toString()}/channels/${this.channel.id}/messages/${this.id}`,{
headers:this.headers,
method:"DELETE",
})
}
deleteEvent(){
if(this.div){
this.div.innerHTML="";
this.div=null;
}
const index=this.channel.messages.indexOf(this);
this.channel.messages.splice(this.channel.messages.indexOf(this),1);
delete this.channel.messageids[this.id];
const regen=this.channel.messages[index-1]
if(regen){
regen.generateMessage();
}
}
generateMessage(premessage:Message=null){
if(!premessage){
premessage=this.channel.messages[this.channel.messages.indexOf(this)+1];
}
const div=this.div;
div.innerHTML="";
const build = document.createElement('table');
const div=document.createElement("div");
if(this.message_reference){
const replyline=document.createElement("div");
const line=document.createElement("hr");
@ -130,7 +175,21 @@ class Message{
username.classList.add("username");
Member.resolve(this.author,this.guild).then(_=>{
if(!_) {return};
console.log(_.error);
if(_.error){
username.textContent+="Error";
alert("Should've gotten here")
const error=document.createElement("span");
error.textContent="!";
error.classList.add("membererror");
username.after(error);
return;
}
username.style.color=_.getColor();
}).catch(_=>{
console.log(_)
});
reply.classList.add("replytext");
@ -161,7 +220,6 @@ class Message{
let pfpparent, current
if(premessage!=null){
pfpparent=premessage.pfpparent;
pfpparent??=premessage;
let pfpparent2=pfpparent.all;
pfpparent2??=pfpparent;
@ -169,7 +227,7 @@ class Message{
const newt=(new Date(this.timestamp).getTime())/1000;
current=(newt-old)>600;
}
const combine=(premessage?.userid!=this.author.id&&premessage?.author?.id!=this.author.id)||(current)||this.message_reference
const combine=(premessage?.author?.id!=this.author.id)||(current)||this.message_reference
if(combine){
const pfp=this.author.buildpfp();
this.author.profileclick(pfp);
@ -189,7 +247,15 @@ class Message{
username.classList.add("username")
this.author.profileclick(username);
Member.resolve(this.author,this.guild).then(_=>{
if(!_){return}
if(!_) {return};
if(_.error){
const error=document.createElement("span");
error.textContent="!";
error.classList.add("membererror");
username.after(error);
return;
}
username.style.color=_.getColor();
})
username.textContent=this.author.username;
@ -266,10 +332,16 @@ class Message{
texttxt.appendChild(messagedwrap)
}
div["userid"]=this.author.id;
div["all"]=this;
return(div)
}
buildhtml(premessage:Message){
if(this.div){console.error(`HTML for ${this} already exists, aborting`);return;}
//premessage??=messages.lastChild;
const div=document.createElement("div");
this.div=div;
return this.generateMessage(premessage);
}
createunknown(fname,fsize,src){
const div=document.createElement("table");
div.classList.add("unknownfile");
@ -328,5 +400,5 @@ function formatTime(date) {
return `${date.toLocaleDateString()} at ${formatTime(date)}`;
}
}
Message.setupcmenu();
Message.setup();
export { Message };

View file

@ -138,7 +138,7 @@ h2 {
.pfp {
border-radius: 50%;
width: .5in;
width: 0.5in;
height: .5in;
user-select: none;
cursor: pointer;
@ -599,9 +599,12 @@ textarea {
#settings {
cursor: pointer;
user-select: none;
border-radius: .1in;
border-radius: .3in;
transition: background 1s;
text-align: center;
font-size: .25in;
width: .3in;
height: .3in;
}
#settings:hover {
@ -975,3 +978,13 @@ span {
.spaceright{
margin-right:.1in;
}
.membererror{
display:inline-block;
background:#656500;
height:.15in;
width:.15in;
border-radius:.1in;
text-align:center;
border:solid black .03in;
margin-left:.025in;
}