server/database/entities/Emoji.ts

138 lines
2.7 KiB
TypeScript
Raw Normal View History

import {
BaseEntity,
Column,
Entity,
IsNull,
ManyToOne,
PrimaryGeneratedColumn,
} from "typeorm";
2023-09-12 22:48:10 +02:00
import { APIEmoji } from "~types/entities/emoji";
import { Instance } from "./Instance";
import { Emoji as LysandEmoji } from "~types/lysand/extensions/org.lysand/custom_emojis";
2023-09-12 22:48:10 +02:00
2023-09-28 20:19:21 +02:00
/**
* Represents an emoji entity in the database.
*/
2023-09-12 22:48:10 +02:00
@Entity({
name: "emojis",
})
export class Emoji extends BaseEntity {
2023-09-28 20:19:21 +02:00
/**
* The unique identifier for the emoji.
*/
2023-09-12 22:48:10 +02:00
@PrimaryGeneratedColumn("uuid")
id!: string;
2023-09-28 20:19:21 +02:00
/**
* The shortcode for the emoji.
*/
2023-09-12 22:48:10 +02:00
@Column("varchar")
shortcode!: string;
/**
* The instance that the emoji is from.
* If is null, the emoji is from the server's instance
*/
@ManyToOne(() => Instance, {
nullable: true,
})
instance!: Instance | null;
2023-09-28 20:19:21 +02:00
/**
* The URL for the emoji.
*/
2023-09-12 22:48:10 +02:00
@Column("varchar")
url!: string;
/**
* The alt text for the emoji.
*/
@Column("varchar", {
nullable: true,
})
alt!: string | null;
/**
* The content type of the emoji.
*/
@Column("varchar")
content_type!: string;
2023-09-28 20:19:21 +02:00
/**
* Whether the emoji is visible in the picker.
*/
2023-09-12 22:48:10 +02:00
@Column("boolean")
visible_in_picker!: boolean;
/**
* Used for parsing emojis from local text
* @param text The text to parse
* @returns An array of emojis
*/
static async parseEmojis(text: string): Promise<Emoji[]> {
const regex = /:[a-zA-Z0-9_]+:/g;
const matches = text.match(regex);
if (!matches) return [];
return (
await Promise.all(
matches.map(match =>
Emoji.findOne({
where: {
shortcode: match.slice(1, -1),
instance: IsNull(),
},
relations: ["instance"],
})
)
)
).filter(emoji => emoji !== null) as Emoji[];
}
static async addIfNotExists(emoji: LysandEmoji) {
const existingEmoji = await Emoji.findOne({
where: {
shortcode: emoji.name,
instance: IsNull(),
},
});
if (existingEmoji) return existingEmoji;
const newEmoji = new Emoji();
newEmoji.shortcode = emoji.name;
// TODO: Content types
newEmoji.url = emoji.url[0].content;
newEmoji.alt = emoji.alt || null;
newEmoji.content_type = emoji.url[0].content_type;
newEmoji.visible_in_picker = true;
await newEmoji.save();
return newEmoji;
}
2023-09-28 20:19:21 +02:00
/**
* Converts the emoji to an APIEmoji object.
* @returns The APIEmoji object.
*/
2023-09-12 22:48:10 +02:00
// eslint-disable-next-line @typescript-eslint/require-await
async toAPI(): Promise<APIEmoji> {
return {
shortcode: this.shortcode,
static_url: this.url, // TODO: Add static version
url: this.url,
visible_in_picker: this.visible_in_picker,
2023-09-12 22:48:10 +02:00
category: undefined,
2023-09-13 02:29:13 +02:00
};
2023-09-12 22:48:10 +02:00
}
toLysand(): LysandEmoji {
return {
name: this.shortcode,
url: [
{
content: this.url,
content_type: this.content_type,
},
],
alt: this.alt || undefined,
};
}
2023-09-13 02:29:13 +02:00
}