386 lines
15 KiB
JavaScript
386 lines
15 KiB
JavaScript
import { Dialog } from "./dialog.js";
|
|
import { MarkDown } from "./markdown.js";
|
|
import { getapiurls, getInstances } from "./login.js";
|
|
import { Guild } from "./guild.js";
|
|
class Embed {
|
|
type;
|
|
owner;
|
|
json;
|
|
constructor(json, owner) {
|
|
this.type = this.getType(json);
|
|
this.owner = owner;
|
|
this.json = json;
|
|
console.log(this);
|
|
}
|
|
getType(json) {
|
|
const instances = getInstances();
|
|
if (instances && json.type === "link" && json.url && URL.canParse(json.url)) {
|
|
const Url = new URL(json.url);
|
|
for (const instance of instances) {
|
|
if (instance.url && URL.canParse(instance.url)) {
|
|
const IUrl = new URL(instance.url);
|
|
const params = new URLSearchParams(Url.search);
|
|
let host;
|
|
if (params.has("instance")) {
|
|
const url = params.get("instance");
|
|
if (URL.canParse(url)) {
|
|
host = new URL(url).host;
|
|
}
|
|
else {
|
|
host = Url.host;
|
|
}
|
|
}
|
|
else {
|
|
host = Url.host;
|
|
}
|
|
if (IUrl.host === host) {
|
|
const code = Url.pathname.split("/")[Url.pathname.split("/").length - 1];
|
|
json.invite = {
|
|
url: instance.url,
|
|
code
|
|
};
|
|
return "invite";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return json.type || "rich";
|
|
}
|
|
generateHTML() {
|
|
switch (this.type) {
|
|
case "rich":
|
|
return this.generateRich();
|
|
case "image":
|
|
return this.generateImage();
|
|
case "invite":
|
|
return this.generateInvite();
|
|
case "link":
|
|
return this.generateLink();
|
|
case "video":
|
|
case "article":
|
|
return this.generateArticle();
|
|
default:
|
|
console.warn(`unsupported embed type ${this.type}, please add support dev :3`, this.json);
|
|
return document.createElement("div"); //prevent errors by giving blank div
|
|
}
|
|
}
|
|
get message() {
|
|
return this.owner;
|
|
}
|
|
get channel() {
|
|
return this.message.channel;
|
|
}
|
|
get guild() {
|
|
return this.channel.guild;
|
|
}
|
|
get localuser() {
|
|
return this.guild.localuser;
|
|
}
|
|
generateRich() {
|
|
const div = document.createElement("div");
|
|
if (this.json.color) {
|
|
div.style.backgroundColor = "#" + this.json.color.toString(16);
|
|
}
|
|
div.classList.add("embed-color");
|
|
const embed = document.createElement("div");
|
|
embed.classList.add("embed");
|
|
div.append(embed);
|
|
if (this.json.author) {
|
|
const authorline = document.createElement("div");
|
|
if (this.json.author.icon_url) {
|
|
const img = document.createElement("img");
|
|
img.classList.add("embedimg");
|
|
img.src = this.json.author.icon_url;
|
|
authorline.append(img);
|
|
}
|
|
const a = document.createElement("a");
|
|
a.textContent = this.json.author.name;
|
|
if (this.json.author.url) {
|
|
MarkDown.safeLink(a, this.json.author.url);
|
|
}
|
|
a.classList.add("username");
|
|
authorline.append(a);
|
|
embed.append(authorline);
|
|
}
|
|
if (this.json.title) {
|
|
const title = document.createElement("a");
|
|
title.append(new MarkDown(this.json.title, this.channel).makeHTML());
|
|
if (this.json.url) {
|
|
MarkDown.safeLink(title, this.json.url);
|
|
}
|
|
title.classList.add("embedtitle");
|
|
embed.append(title);
|
|
}
|
|
if (this.json.description) {
|
|
const p = document.createElement("p");
|
|
p.append(new MarkDown(this.json.description, this.channel).makeHTML());
|
|
embed.append(p);
|
|
}
|
|
embed.append(document.createElement("br"));
|
|
if (this.json.fields) {
|
|
for (const thing of this.json.fields) {
|
|
const div = document.createElement("div");
|
|
const b = document.createElement("b");
|
|
b.textContent = thing.name;
|
|
div.append(b);
|
|
const p = document.createElement("p");
|
|
p.append(new MarkDown(thing.value, this.channel).makeHTML());
|
|
p.classList.add("embedp");
|
|
div.append(p);
|
|
if (thing.inline) {
|
|
div.classList.add("inline");
|
|
}
|
|
embed.append(div);
|
|
}
|
|
}
|
|
if (this.json.footer || this.json.timestamp) {
|
|
const footer = document.createElement("div");
|
|
if (this.json?.footer?.icon_url) {
|
|
const img = document.createElement("img");
|
|
img.src = this.json.footer.icon_url;
|
|
img.classList.add("embedicon");
|
|
footer.append(img);
|
|
}
|
|
if (this.json?.footer?.text) {
|
|
const span = document.createElement("span");
|
|
span.textContent = this.json.footer.text;
|
|
span.classList.add("spaceright");
|
|
footer.append(span);
|
|
}
|
|
if (this.json?.footer && this.json?.timestamp) {
|
|
const span = document.createElement("span");
|
|
span.textContent = "•";
|
|
span.classList.add("spaceright");
|
|
footer.append(span);
|
|
}
|
|
if (this.json?.timestamp) {
|
|
const span = document.createElement("span");
|
|
span.textContent = new Date(this.json.timestamp).toLocaleString();
|
|
footer.append(span);
|
|
}
|
|
embed.append(footer);
|
|
}
|
|
return div;
|
|
}
|
|
generateImage() {
|
|
const img = document.createElement("img");
|
|
img.classList.add("messageimg");
|
|
img.onclick = function () {
|
|
const full = new Dialog(["img", img.src, ["fit"]]);
|
|
full.show();
|
|
};
|
|
img.src = this.json.thumbnail.proxy_url;
|
|
if (this.json.thumbnail.width) {
|
|
let scale = 1;
|
|
const max = 96 * 3;
|
|
scale = Math.max(scale, this.json.thumbnail.width / max);
|
|
scale = Math.max(scale, this.json.thumbnail.height / max);
|
|
this.json.thumbnail.width /= scale;
|
|
this.json.thumbnail.height /= scale;
|
|
}
|
|
img.style.width = this.json.thumbnail.width + "px";
|
|
img.style.height = this.json.thumbnail.height + "px";
|
|
console.log(this.json, "Image fix");
|
|
return img;
|
|
}
|
|
generateLink() {
|
|
const table = document.createElement("table");
|
|
table.classList.add("embed", "linkembed");
|
|
const trtop = document.createElement("tr");
|
|
table.append(trtop);
|
|
if (this.json.url && this.json.title) {
|
|
const td = document.createElement("td");
|
|
const a = document.createElement("a");
|
|
MarkDown.safeLink(a, this.json.url);
|
|
a.textContent = this.json.title;
|
|
td.append(a);
|
|
trtop.append(td);
|
|
}
|
|
{
|
|
const td = document.createElement("td");
|
|
const img = document.createElement("img");
|
|
if (this.json.thumbnail) {
|
|
img.classList.add("embedimg");
|
|
img.onclick = function () {
|
|
const full = new Dialog(["img", img.src, ["fit"]]);
|
|
full.show();
|
|
};
|
|
img.src = this.json.thumbnail.proxy_url;
|
|
td.append(img);
|
|
}
|
|
trtop.append(td);
|
|
}
|
|
const bottomtr = document.createElement("tr");
|
|
const td = document.createElement("td");
|
|
if (this.json.description) {
|
|
const span = document.createElement("span");
|
|
span.textContent = this.json.description;
|
|
td.append(span);
|
|
}
|
|
bottomtr.append(td);
|
|
table.append(bottomtr);
|
|
return table;
|
|
}
|
|
invcache;
|
|
generateInvite() {
|
|
if (this.invcache && (!this.json.invite || !this.localuser)) {
|
|
return this.generateLink();
|
|
}
|
|
const div = document.createElement("div");
|
|
div.classList.add("embed", "inviteEmbed", "flexttb");
|
|
const json1 = this.json.invite;
|
|
(async () => {
|
|
let json;
|
|
let info;
|
|
if (!this.invcache) {
|
|
if (!json1) {
|
|
div.append(this.generateLink());
|
|
return;
|
|
}
|
|
const tempinfo = await getapiurls(json1.url);
|
|
;
|
|
if (!tempinfo) {
|
|
div.append(this.generateLink());
|
|
return;
|
|
}
|
|
info = tempinfo;
|
|
const res = await fetch(info.api + "/invites/" + json1.code);
|
|
if (!res.ok) {
|
|
div.append(this.generateLink());
|
|
}
|
|
json = await res.json();
|
|
this.invcache = [json, info];
|
|
}
|
|
else {
|
|
[json, info] = this.invcache;
|
|
}
|
|
if (!json) {
|
|
div.append(this.generateLink());
|
|
return;
|
|
}
|
|
if (json.guild.banner) {
|
|
const banner = document.createElement("img");
|
|
banner.src = this.localuser.info.cdn + "/icons/" + json.guild.id + "/" + json.guild.banner + ".png?size=256";
|
|
banner.classList.add("banner");
|
|
div.append(banner);
|
|
}
|
|
const guild = json.guild;
|
|
guild.info = info;
|
|
const icon = Guild.generateGuildIcon(guild);
|
|
const iconrow = document.createElement("div");
|
|
iconrow.classList.add("flexltr", "flexstart");
|
|
iconrow.append(icon);
|
|
{
|
|
const guildinfo = document.createElement("div");
|
|
guildinfo.classList.add("flexttb", "invguildinfo");
|
|
const name = document.createElement("b");
|
|
name.textContent = guild.name;
|
|
guildinfo.append(name);
|
|
const members = document.createElement("span");
|
|
members.innerText = "#" + json.channel.name + " • Members: " + guild.member_count;
|
|
guildinfo.append(members);
|
|
members.classList.add("subtext");
|
|
iconrow.append(guildinfo);
|
|
}
|
|
div.append(iconrow);
|
|
const h2 = document.createElement("h2");
|
|
h2.textContent = `You've been invited by ${json.inviter.username}`;
|
|
div.append(h2);
|
|
const button = document.createElement("button");
|
|
button.textContent = "Accept";
|
|
if (this.localuser.info.api.startsWith(info.api)) {
|
|
if (this.localuser.guildids.has(guild.id)) {
|
|
button.textContent = "Already joined";
|
|
button.disabled = true;
|
|
}
|
|
}
|
|
button.classList.add("acceptinvbutton");
|
|
div.append(button);
|
|
button.onclick = _ => {
|
|
if (this.localuser.info.api.startsWith(info.api)) {
|
|
fetch(this.localuser.info.api + "/invites/" + json.code, {
|
|
method: "POST",
|
|
headers: this.localuser.headers,
|
|
}).then(r => r.json()).then(_ => {
|
|
if (_.message) {
|
|
alert(_.message);
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
if (this.json.invite) {
|
|
const params = new URLSearchParams("");
|
|
params.set("instance", this.json.invite.url);
|
|
const encoded = params.toString();
|
|
const url = `${location.origin}/invite/${this.json.invite.code}?${encoded}`;
|
|
window.open(url, "_blank");
|
|
}
|
|
}
|
|
};
|
|
})();
|
|
return div;
|
|
}
|
|
generateArticle() {
|
|
const colordiv = document.createElement("div");
|
|
colordiv.style.backgroundColor = "#000000";
|
|
colordiv.classList.add("embed-color");
|
|
const div = document.createElement("div");
|
|
div.classList.add("embed");
|
|
if (this.json.provider) {
|
|
const provider = document.createElement("p");
|
|
provider.classList.add("provider");
|
|
provider.textContent = this.json.provider.name;
|
|
div.append(provider);
|
|
}
|
|
const a = document.createElement("a");
|
|
if (this.json.url && this.json.url) {
|
|
MarkDown.safeLink(a, this.json.url);
|
|
a.textContent = this.json.url;
|
|
div.append(a);
|
|
}
|
|
if (this.json.description) {
|
|
const description = document.createElement("p");
|
|
description.textContent = this.json.description;
|
|
div.append(description);
|
|
}
|
|
if (this.json.thumbnail) {
|
|
const img = document.createElement("img");
|
|
if (this.json.thumbnail.width && this.json.thumbnail.width) {
|
|
let scale = 1;
|
|
const inch = 96;
|
|
scale = Math.max(scale, this.json.thumbnail.width / inch / 4);
|
|
scale = Math.max(scale, this.json.thumbnail.height / inch / 3);
|
|
this.json.thumbnail.width /= scale;
|
|
this.json.thumbnail.height /= scale;
|
|
img.style.width = this.json.thumbnail.width + "px";
|
|
img.style.height = this.json.thumbnail.height + "px";
|
|
}
|
|
img.classList.add("bigembedimg");
|
|
if (this.json.video) {
|
|
img.onclick = async () => {
|
|
if (this.json.video) {
|
|
img.remove();
|
|
const iframe = document.createElement("iframe");
|
|
iframe.src = this.json.video.url + "?autoplay=1";
|
|
if (this.json.thumbnail.width && this.json.thumbnail.width) {
|
|
iframe.style.width = this.json.thumbnail.width + "px";
|
|
iframe.style.height = this.json.thumbnail.height + "px";
|
|
}
|
|
div.append(iframe);
|
|
}
|
|
};
|
|
}
|
|
else {
|
|
img.onclick = async () => {
|
|
const full = new Dialog(["img", img.src, ["fit"]]);
|
|
full.show();
|
|
};
|
|
}
|
|
img.src = this.json.thumbnail.proxy_url || this.json.thumbnail.url;
|
|
div.append(img);
|
|
}
|
|
colordiv.append(div);
|
|
return colordiv;
|
|
}
|
|
}
|
|
export { Embed };
|