392 lines
11 KiB
TypeScript
392 lines
11 KiB
TypeScript
import{Dialog}from"./dialog.js";
|
|
import{Message}from"./message.js";
|
|
import{MarkDown}from"./markdown.js";
|
|
import{ embedjson,guildjson, invitejson }from"./jsontypes.js";
|
|
import { getapiurls, getInstances } from "./login.js";
|
|
import { Guild } from "./guild.js";
|
|
|
|
class Embed{
|
|
type:string;
|
|
owner:Message;
|
|
json:embedjson;
|
|
constructor(json:embedjson, owner:Message){
|
|
this.type=this.getType(json);
|
|
this.owner=owner;
|
|
this.json=json;
|
|
console.log(this);
|
|
}
|
|
getType(json:embedjson){
|
|
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:string;
|
|
if(params.has("instance")){
|
|
const url=params.get("instance") as string;
|
|
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 as string;
|
|
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:[invitejson,{cdn:string,api:string}]|undefined;
|
|
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:invitejson;
|
|
let info:{cdn:string,api:string};
|
|
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() as invitejson;
|
|
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:invitejson["guild"] & {info?:{cdn:string}}=json.guild;
|
|
guild.info=info;
|
|
const icon=Guild.generateGuildIcon(guild as invitejson["guild"] & {info:{cdn:string}})
|
|
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};
|