mirror of
https://github.com/stoatchat/javascript-client-sdk.git
synced 2026-07-18 16:34:27 -04:00
228 lines
5.7 KiB
TypeScript
228 lines
5.7 KiB
TypeScript
import type { Embed, ImageSize, Special } from "stoat-api";
|
|
|
|
import type { Client } from "../Client.js";
|
|
|
|
import { File } from "./File.js";
|
|
|
|
/**
|
|
* Message Embed
|
|
*/
|
|
export abstract class MessageEmbed {
|
|
protected client?: Client;
|
|
readonly type: Embed["type"];
|
|
|
|
/**
|
|
* Construct Embed
|
|
* @param client Client
|
|
* @param type Type
|
|
*/
|
|
constructor(client?: Client, type: Embed["type"] = "None") {
|
|
this.client = client;
|
|
this.type = type;
|
|
}
|
|
|
|
/**
|
|
* Create an Embed from an API Embed
|
|
* @param client Client
|
|
* @param embed Data
|
|
* @returns Embed
|
|
*/
|
|
static from(client: Client, embed: Embed): MessageEmbed {
|
|
switch (embed.type) {
|
|
case "Image":
|
|
return new ImageEmbed(client, embed);
|
|
case "Video":
|
|
return new VideoEmbed(client, embed);
|
|
case "Website":
|
|
return new WebsiteEmbed(client, embed);
|
|
case "Text":
|
|
return new TextEmbed(client, embed);
|
|
default:
|
|
return new UnknownEmbed(client);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Embed of unknown type
|
|
*/
|
|
export class UnknownEmbed extends MessageEmbed {}
|
|
|
|
/**
|
|
* Image Embed
|
|
*/
|
|
export class ImageEmbed extends MessageEmbed {
|
|
readonly url: string;
|
|
readonly width: number;
|
|
readonly height: number;
|
|
readonly size: ImageSize;
|
|
|
|
/**
|
|
* Construct Image Embed
|
|
* @param client Client
|
|
* @param embed Embed
|
|
*/
|
|
constructor(client: Client, embed: Omit<Embed & { type: "Image" }, "type">) {
|
|
super(client, "Image");
|
|
|
|
this.url = embed.url;
|
|
this.width = embed.width;
|
|
this.height = embed.height;
|
|
this.size = embed.size;
|
|
}
|
|
|
|
/**
|
|
* Proxied image URL
|
|
*/
|
|
get proxiedURL(): string | undefined {
|
|
return this.client?.proxyFile(this.url);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Video Embed
|
|
*/
|
|
export class VideoEmbed extends MessageEmbed {
|
|
readonly url: string;
|
|
readonly width: number;
|
|
readonly height: number;
|
|
|
|
/**
|
|
* Construct Video Embed
|
|
* @param client Client
|
|
* @param embed Embed
|
|
*/
|
|
constructor(client: Client, embed: Omit<Embed & { type: "Video" }, "type">) {
|
|
super(client, "Video");
|
|
|
|
this.url = embed.url;
|
|
this.width = embed.width;
|
|
this.height = embed.height;
|
|
}
|
|
|
|
/**
|
|
* Proxied video URL
|
|
*/
|
|
get proxiedURL(): string | undefined {
|
|
return this.client?.proxyFile(this.url);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Website Embed
|
|
*/
|
|
export class WebsiteEmbed extends MessageEmbed {
|
|
readonly url?: string;
|
|
readonly originalUrl?: string;
|
|
readonly specialContent?: Special;
|
|
readonly title?: string;
|
|
readonly description?: string;
|
|
readonly image?: ImageEmbed;
|
|
readonly video?: VideoEmbed;
|
|
readonly siteName?: string;
|
|
readonly iconUrl?: string;
|
|
readonly colour?: string;
|
|
|
|
/**
|
|
* Construct Video Embed
|
|
* @param client Client
|
|
* @param embed Embed
|
|
*/
|
|
constructor(
|
|
client: Client,
|
|
embed: Omit<Embed & { type: "Website" }, "type">,
|
|
) {
|
|
super(client, "Website");
|
|
|
|
this.url = embed.url!;
|
|
this.originalUrl = embed.original_url!;
|
|
this.specialContent = embed.special!;
|
|
this.title = embed.title!;
|
|
this.description = embed.description!;
|
|
this.image = embed.image ? new ImageEmbed(client, embed.image) : undefined;
|
|
this.video = embed.video ? new VideoEmbed(client, embed.video) : undefined;
|
|
this.siteName = embed.site_name!;
|
|
this.iconUrl = embed.icon_url!;
|
|
this.colour = embed.colour!;
|
|
}
|
|
|
|
/**
|
|
* Proxied icon URL
|
|
*/
|
|
get proxiedIconURL(): string | undefined {
|
|
return this.iconUrl ? this.client?.proxyFile(this.iconUrl) : undefined;
|
|
}
|
|
|
|
/**
|
|
* If special content is present, generate the embed URL
|
|
*/
|
|
get embedURL(): string | undefined {
|
|
switch (this.specialContent?.type) {
|
|
case "YouTube": {
|
|
let timestamp = "";
|
|
|
|
if (this.specialContent.timestamp) {
|
|
timestamp = `&start=${this.specialContent.timestamp}`;
|
|
}
|
|
|
|
return `https://www.youtube-nocookie.com/embed/${this.specialContent.id}?modestbranding=1${timestamp}`;
|
|
}
|
|
case "Twitch":
|
|
return `https://player.twitch.tv/?${this.specialContent.content_type.toLowerCase()}=${
|
|
this.specialContent.id
|
|
}&parent=${(window ?? {})?.location?.hostname}&autoplay=false`;
|
|
case "Lightspeed":
|
|
return `https://new.lightspeed.tv/embed/${this.specialContent.id}/stream`;
|
|
case "Spotify":
|
|
return `https://open.spotify.com/embed/${this.specialContent.content_type}/${this.specialContent.id}`;
|
|
case "Soundcloud":
|
|
return `https://w.soundcloud.com/player/?url=${encodeURIComponent(
|
|
this.url!,
|
|
)}&color=%23FF7F50&auto_play=false&hide_related=false&show_comments=true&show_user=true&show_reposts=false&show_teaser=true&visual=true`;
|
|
case "Bandcamp": {
|
|
return `https://bandcamp.com/EmbeddedPlayer/${this.specialContent.content_type.toLowerCase()}=${
|
|
this.specialContent.id
|
|
}/size=large/bgcol=181a1b/linkcol=056cc4/tracklist=false/transparent=true/`;
|
|
}
|
|
case "Streamable": {
|
|
return `https://streamable.com/e/${this.specialContent.id}?loop=0`;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Text Embed
|
|
*/
|
|
export class TextEmbed extends MessageEmbed {
|
|
readonly iconUrl?: string;
|
|
readonly url?: string;
|
|
readonly title?: string;
|
|
readonly description?: string;
|
|
readonly media?: File;
|
|
readonly colour?: string;
|
|
|
|
/**
|
|
* Construct Video Embed
|
|
* @param client Client
|
|
* @param embed Embed
|
|
*/
|
|
constructor(client: Client, embed: Omit<Embed & { type: "Text" }, "type">) {
|
|
super(client, "Text");
|
|
|
|
this.iconUrl = embed.icon_url!;
|
|
this.url = embed.url!;
|
|
this.title = embed.title!;
|
|
this.description = embed.description!;
|
|
this.media = embed.media ? new File(client, embed.media) : undefined;
|
|
this.colour = embed.colour!;
|
|
}
|
|
|
|
/**
|
|
* Proxied icon URL
|
|
*/
|
|
get proxiedIconURL(): string | undefined {
|
|
return this.iconUrl ? this.client?.proxyFile(this.iconUrl) : undefined;
|
|
}
|
|
}
|