431 lines
14 KiB
JavaScript
431 lines
14 KiB
JavaScript
//const usercache={};
|
|
import { Member } from "./member.js";
|
|
import { MarkDown } from "./markdown.js";
|
|
import { Contextmenu } from "./contextmenu.js";
|
|
import { SnowFlake } from "./snowflake.js";
|
|
class User extends SnowFlake {
|
|
owner;
|
|
hypotheticalpfp;
|
|
avatar;
|
|
username;
|
|
nickname = null;
|
|
relationshipType = 0;
|
|
bio;
|
|
discriminator;
|
|
pronouns;
|
|
bot;
|
|
public_flags;
|
|
accent_color;
|
|
banner;
|
|
hypotheticalbanner;
|
|
premium_since;
|
|
premium_type;
|
|
theme_colors;
|
|
badge_ids;
|
|
members = new WeakMap();
|
|
status;
|
|
clone() {
|
|
return new User({
|
|
username: this.username,
|
|
id: this.id + "#clone",
|
|
public_flags: this.public_flags,
|
|
discriminator: this.discriminator,
|
|
avatar: this.avatar,
|
|
accent_color: this.accent_color,
|
|
banner: this.banner,
|
|
bio: this.bio.rawString,
|
|
premium_since: this.premium_since,
|
|
premium_type: this.premium_type,
|
|
bot: this.bot,
|
|
theme_colors: this.theme_colors,
|
|
pronouns: this.pronouns,
|
|
badge_ids: this.badge_ids
|
|
}, this.owner);
|
|
}
|
|
getPresence(presence) {
|
|
if (presence) {
|
|
this.setstatus(presence.status);
|
|
}
|
|
else {
|
|
this.setstatus("offline");
|
|
}
|
|
}
|
|
setstatus(status) {
|
|
this.status = status;
|
|
}
|
|
async getStatus() {
|
|
if (this.status) {
|
|
return this.status;
|
|
}
|
|
else {
|
|
return "offline";
|
|
}
|
|
}
|
|
static contextmenu = new Contextmenu("User Menu");
|
|
static setUpContextMenu() {
|
|
this.contextmenu.addbutton("Copy user id", function () {
|
|
navigator.clipboard.writeText(this.id);
|
|
});
|
|
this.contextmenu.addbutton("Message user", function () {
|
|
fetch(this.info.api + "/users/@me/channels", { method: "POST",
|
|
body: JSON.stringify({ recipients: [this.id] }),
|
|
headers: this.localuser.headers
|
|
}).then(_ => _.json()).then(json => {
|
|
this.localuser.goToChannel(json.id);
|
|
});
|
|
});
|
|
this.contextmenu.addbutton("Block user", function () {
|
|
this.block();
|
|
}, null, function () {
|
|
return this.relationshipType !== 2;
|
|
});
|
|
this.contextmenu.addbutton("Unblock user", function () {
|
|
this.unblock();
|
|
}, null, function () {
|
|
return this.relationshipType === 2;
|
|
});
|
|
this.contextmenu.addbutton("Friend request", function () {
|
|
fetch(`${this.info.api}/users/@me/relationships/${this.id}`, {
|
|
method: "PUT",
|
|
headers: this.owner.headers,
|
|
body: JSON.stringify({
|
|
type: 1
|
|
})
|
|
});
|
|
});
|
|
this.contextmenu.addbutton("Kick member", function (member) {
|
|
member.kick();
|
|
}, null, member => {
|
|
if (!member)
|
|
return false;
|
|
const us = member.guild.member;
|
|
if (member.id === us.id) {
|
|
return false;
|
|
}
|
|
if (member.id === member.guild.properties.owner_id) {
|
|
return false;
|
|
}
|
|
return (us.hasPermission("KICK_MEMBERS")) || false;
|
|
});
|
|
this.contextmenu.addbutton("Ban member", function (member) {
|
|
member.ban();
|
|
}, null, member => {
|
|
if (!member)
|
|
return false;
|
|
const us = member.guild.member;
|
|
if (member.id === us.id) {
|
|
return false;
|
|
}
|
|
if (member.id === member.guild.properties.owner_id) {
|
|
return false;
|
|
}
|
|
return (us.hasPermission("BAN_MEMBERS")) || false;
|
|
});
|
|
}
|
|
static checkuser(user, owner) {
|
|
if (owner.userMap.has(user.id)) {
|
|
return owner.userMap.get(user.id);
|
|
}
|
|
else {
|
|
const tempuser = new User(user, owner, true);
|
|
owner.userMap.set(user.id, tempuser);
|
|
return tempuser;
|
|
}
|
|
}
|
|
get info() {
|
|
return this.owner.info;
|
|
}
|
|
get localuser() {
|
|
return this.owner;
|
|
}
|
|
get name() {
|
|
return this.username;
|
|
}
|
|
constructor(userjson, owner, dontclone = false) {
|
|
super(userjson.id);
|
|
this.owner = owner;
|
|
if (!owner) {
|
|
console.error("missing localuser");
|
|
}
|
|
if (dontclone) {
|
|
for (const thing of Object.keys(userjson)) {
|
|
if (thing === "bio") {
|
|
this.bio = new MarkDown(userjson[thing], this.localuser);
|
|
continue;
|
|
}
|
|
if (thing === "id") {
|
|
continue;
|
|
}
|
|
this[thing] = userjson[thing];
|
|
}
|
|
this.hypotheticalpfp = false;
|
|
}
|
|
else {
|
|
return User.checkuser(userjson, owner);
|
|
}
|
|
}
|
|
async resolvemember(guild) {
|
|
return await Member.resolveMember(this, guild);
|
|
}
|
|
async getUserProfile() {
|
|
return (await fetch(`${this.info.api}/users/${this.id.replace("#clone", "")}/profile?with_mutual_guilds=true&with_mutual_friends=true`, {
|
|
headers: this.localuser.headers
|
|
})).json();
|
|
}
|
|
resolving = false;
|
|
async getBadge(id) {
|
|
if (this.localuser.badges.has(id)) {
|
|
return this.localuser.badges.get(id);
|
|
}
|
|
else {
|
|
if (this.resolving) {
|
|
await this.resolving;
|
|
return this.localuser.badges.get(id);
|
|
}
|
|
const prom = await this.getUserProfile();
|
|
this.resolving = prom;
|
|
const badges = prom.badges;
|
|
this.resolving = false;
|
|
for (const thing of badges) {
|
|
this.localuser.badges.set(thing.id, thing);
|
|
}
|
|
return this.localuser.badges.get(id);
|
|
}
|
|
}
|
|
buildpfp() {
|
|
const pfp = document.createElement("img");
|
|
pfp.loading = "lazy";
|
|
pfp.src = this.getpfpsrc();
|
|
pfp.classList.add("pfp");
|
|
pfp.classList.add("userid:" + this.id);
|
|
return pfp;
|
|
}
|
|
async buildstatuspfp() {
|
|
const div = document.createElement("div");
|
|
div.style.position = "relative";
|
|
const pfp = this.buildpfp();
|
|
div.append(pfp);
|
|
{
|
|
const status = document.createElement("div");
|
|
status.classList.add("statusDiv");
|
|
switch (await this.getStatus()) {
|
|
case "offline":
|
|
status.classList.add("offlinestatus");
|
|
break;
|
|
case "online":
|
|
default:
|
|
status.classList.add("onlinestatus");
|
|
break;
|
|
}
|
|
div.append(status);
|
|
}
|
|
return div;
|
|
}
|
|
userupdate(json) {
|
|
if (json.avatar !== this.avatar) {
|
|
console.log;
|
|
this.changepfp(json.avatar);
|
|
}
|
|
}
|
|
bind(html, guild = null, error = true) {
|
|
if (guild && guild.id !== "@me") {
|
|
Member.resolveMember(this, guild).then(_ => {
|
|
User.contextmenu.bindContextmenu(html, this, _);
|
|
if (_ === undefined && error) {
|
|
const error = document.createElement("span");
|
|
error.textContent = "!";
|
|
error.classList.add("membererror");
|
|
html.after(error);
|
|
return;
|
|
}
|
|
if (_) {
|
|
_.bind(html);
|
|
}
|
|
}).catch(_ => {
|
|
console.log(_);
|
|
});
|
|
}
|
|
if (guild) {
|
|
this.profileclick(html, guild);
|
|
}
|
|
else {
|
|
this.profileclick(html);
|
|
}
|
|
}
|
|
static async resolve(id, localuser) {
|
|
const json = await fetch(localuser.info.api.toString() + "/users/" + id + "/profile", { headers: localuser.headers }).then(_ => _.json());
|
|
return new User(json, localuser);
|
|
}
|
|
changepfp(update) {
|
|
this.avatar = update;
|
|
this.hypotheticalpfp = false;
|
|
const src = this.getpfpsrc();
|
|
console.log(src);
|
|
for (const thing of document.getElementsByClassName("userid:" + this.id)) {
|
|
thing.src = src;
|
|
}
|
|
}
|
|
block() {
|
|
fetch(`${this.info.api}/users/@me/relationships/${this.id}`, {
|
|
method: "PUT",
|
|
headers: this.owner.headers,
|
|
body: JSON.stringify({
|
|
type: 2
|
|
})
|
|
});
|
|
this.relationshipType = 2;
|
|
const channel = this.localuser.channelfocus;
|
|
if (channel) {
|
|
for (const thing of channel.messages) {
|
|
thing[1].generateMessage();
|
|
}
|
|
}
|
|
}
|
|
unblock() {
|
|
fetch(`${this.info.api}/users/@me/relationships/${this.id}`, {
|
|
method: "DELETE",
|
|
headers: this.owner.headers,
|
|
});
|
|
this.relationshipType = 0;
|
|
const channel = this.localuser.channelfocus;
|
|
if (channel) {
|
|
for (const thing of channel.messages) {
|
|
thing[1].generateMessage();
|
|
}
|
|
}
|
|
}
|
|
getpfpsrc() {
|
|
if (this.hypotheticalpfp && this.avatar) {
|
|
return this.avatar;
|
|
}
|
|
if (this.avatar !== null) {
|
|
return this.info.cdn + "/avatars/" + this.id.replace("#clone", "") + "/" + this.avatar + ".png";
|
|
}
|
|
else {
|
|
const int = new Number((BigInt(this.id.replace("#clone", "")) >> 22n) % 6n);
|
|
return this.info.cdn + `/embed/avatars/${int}.png`;
|
|
}
|
|
}
|
|
createjankpromises() {
|
|
new Promise(_ => { });
|
|
}
|
|
async buildprofile(x, y, guild = null) {
|
|
if (Contextmenu.currentmenu != "") {
|
|
Contextmenu.currentmenu.remove();
|
|
}
|
|
const div = document.createElement("div");
|
|
if (this.accent_color) {
|
|
div.style.setProperty("--accent_color", "#" + this.accent_color.toString(16).padStart(6, "0"));
|
|
}
|
|
else {
|
|
div.style.setProperty("--accent_color", "transparent");
|
|
}
|
|
if (this.banner) {
|
|
const banner = document.createElement("img");
|
|
let src;
|
|
if (!this.hypotheticalbanner) {
|
|
src = this.info.cdn + "/avatars/" + this.id.replace("#clone", "") + "/" + this.banner + ".png";
|
|
}
|
|
else {
|
|
src = this.banner;
|
|
}
|
|
console.log(src, this.banner);
|
|
banner.src = src;
|
|
banner.classList.add("banner");
|
|
div.append(banner);
|
|
}
|
|
if (x !== -1) {
|
|
div.style.left = x + "px";
|
|
div.style.top = y + "px";
|
|
div.classList.add("profile", "flexttb");
|
|
}
|
|
else {
|
|
this.setstatus("online");
|
|
div.classList.add("hypoprofile", "flexttb");
|
|
}
|
|
const badgediv = document.createElement("div");
|
|
badgediv.classList.add("badges");
|
|
(async () => {
|
|
if (!this.badge_ids)
|
|
return;
|
|
for (const id of this.badge_ids) {
|
|
const badgejson = await this.getBadge(id);
|
|
if (badgejson) {
|
|
const badge = document.createElement(badgejson.link ? "a" : "div");
|
|
badge.classList.add("badge");
|
|
const img = document.createElement("img");
|
|
img.src = badgejson.icon;
|
|
badge.append(img);
|
|
const span = document.createElement("span");
|
|
span.textContent = badgejson.description;
|
|
badge.append(span);
|
|
if (badge instanceof HTMLAnchorElement) {
|
|
badge.href = badgejson.link;
|
|
}
|
|
badgediv.append(badge);
|
|
}
|
|
}
|
|
})();
|
|
{
|
|
const pfp = await this.buildstatuspfp();
|
|
div.appendChild(pfp);
|
|
}
|
|
{
|
|
const userbody = document.createElement("div");
|
|
userbody.classList.add("infosection");
|
|
div.appendChild(userbody);
|
|
const usernamehtml = document.createElement("h2");
|
|
usernamehtml.textContent = this.username;
|
|
userbody.appendChild(usernamehtml);
|
|
userbody.appendChild(badgediv);
|
|
const discrimatorhtml = document.createElement("h3");
|
|
discrimatorhtml.classList.add("tag");
|
|
discrimatorhtml.textContent = this.username + "#" + this.discriminator;
|
|
userbody.appendChild(discrimatorhtml);
|
|
const pronounshtml = document.createElement("p");
|
|
pronounshtml.textContent = this.pronouns;
|
|
pronounshtml.classList.add("pronouns");
|
|
userbody.appendChild(pronounshtml);
|
|
const rule = document.createElement("hr");
|
|
userbody.appendChild(rule);
|
|
const biohtml = this.bio.makeHTML();
|
|
userbody.appendChild(biohtml);
|
|
if (guild) {
|
|
Member.resolveMember(this, guild).then(member => {
|
|
if (!member)
|
|
return;
|
|
const roles = document.createElement("div");
|
|
roles.classList.add("rolesbox");
|
|
for (const role of member.roles) {
|
|
const div = document.createElement("div");
|
|
div.classList.add("rolediv");
|
|
const color = document.createElement("div");
|
|
div.append(color);
|
|
color.style.setProperty("--role-color", "#" + role.color.toString(16).padStart(6, "0"));
|
|
color.classList.add("colorrolediv");
|
|
const span = document.createElement("span");
|
|
div.append(span);
|
|
span.textContent = role.name;
|
|
roles.append(div);
|
|
}
|
|
userbody.append(roles);
|
|
});
|
|
}
|
|
}
|
|
console.log(div);
|
|
if (x !== -1) {
|
|
Contextmenu.currentmenu = div;
|
|
document.body.appendChild(div);
|
|
Contextmenu.keepOnScreen(div);
|
|
}
|
|
return div;
|
|
}
|
|
profileclick(obj, guild) {
|
|
obj.onclick = e => {
|
|
this.buildprofile(e.clientX, e.clientY, guild);
|
|
e.stopPropagation();
|
|
};
|
|
}
|
|
}
|
|
User.setUpContextMenu();
|
|
export { User };
|