Newer
Older
percord / util / oldModels / Message.ts
@Flam3rboy Flam3rboy on 21 Aug 2021 8 KB :construction: typeorm
import { Schema, Types, Document } from "mongoose";
import db from "../util/Database";
import { PublicUser, PublicUserProjection, UserModel } from "./User";
import { MemberModel, PublicMember } from "./Member";
import { Role, RoleModel } from "./Role";
import { Channel } from "./Channel";
import { Snowflake } from "../util";
import { InteractionType } from "./Interaction";

export interface Message {
	id: string;
	channel_id: string;
	guild_id?: string;
	author_id?: string;
	webhook_id?: string;
	application_id?: string;
	content?: string;
	timestamp: Date;
	edited_timestamp: Date | null;
	tts?: boolean;
	mention_everyone?: boolean;
	mention_user_ids: string[];
	mention_role_ids: string[];
	mention_channels_ids: string[];
	attachments: Attachment[];
	embeds: Embed[];
	reactions: Reaction[];
	nonce?: string | number;
	pinned?: boolean;
	type: MessageType;
	activity?: {
		type: number;
		party_id: string;
	};
	flags?: bigint;
	stickers?: any[];
	message_reference?: {
		message_id: string;
		channel_id?: string;
		guild_id?: string;
	};
	interaction?: {
		id: string;
		type: InteractionType;
		name: string;
		user_id: string; // the user who invoked the interaction
		// user: User; // TODO: autopopulate user
	};
	components: MessageComponent[];

	// * mongoose virtuals:
	// TODO:
	// application: Application; // TODO: auto pouplate application
	author?: PublicUser;
	member?: PublicMember;
	mentions?: (PublicUser & {
		member: PublicMember;
	})[];
	mention_roles?: Role[];
	mention_channels?: Channel[];
	created_at?: Date;
	// thread // TODO
}

const PartialEmoji = {
	id: String,
	name: { type: String, required: true },
	animated: { type: Boolean, required: true },
};

const MessageComponent: any = {
	type: { type: Number, required: true },
	style: Number,
	label: String,
	emoji: PartialEmoji,
	custom_id: String,
	url: String,
	disabled: Boolean,
	components: [Object],
};

export interface MessageComponent {
	type: number;
	style?: number;
	label?: string;
	emoji?: PartialEmoji;
	custom_id?: string;
	url?: string;
	disabled?: boolean;
	components: MessageComponent[];
}

export enum MessageComponentType {
	ActionRow = 1,
	Button = 2,
}

export interface MessageDocument extends Document, Message {
	id: string;
}

export enum MessageType {
	DEFAULT = 0,
	RECIPIENT_ADD = 1,
	RECIPIENT_REMOVE = 2,
	CALL = 3,
	CHANNEL_NAME_CHANGE = 4,
	CHANNEL_ICON_CHANGE = 5,
	CHANNEL_PINNED_MESSAGE = 6,
	GUILD_MEMBER_JOIN = 7,
	USER_PREMIUM_GUILD_SUBSCRIPTION = 8,
	USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_1 = 9,
	USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_2 = 10,
	USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_3 = 11,
	CHANNEL_FOLLOW_ADD = 12,
	GUILD_DISCOVERY_DISQUALIFIED = 14,
	GUILD_DISCOVERY_REQUALIFIED = 15,
	REPLY = 19,
	APPLICATION_COMMAND = 20,
}

export interface Attachment {
	id: string; // attachment id
	filename: string; // name of file attached
	size: number; // size of file in bytes
	url: string; // source url of file
	proxy_url: string; // a proxied url of file
	height?: number; // height of file (if image)
	width?: number; // width of file (if image)
	content_type?: string;
}

export interface Embed {
	title?: string; //title of embed
	type?: EmbedType; // type of embed (always "rich" for webhook embeds)
	description?: string; // description of embed
	url?: string; // url of embed
	timestamp?: Date; // timestamp of embed content
	color?: number; // color code of the embed
	footer?: {
		text: string;
		icon_url?: string;
		proxy_icon_url?: string;
	}; // footer object	footer information
	image?: EmbedImage; // image object	image information
	thumbnail?: EmbedImage; // thumbnail object	thumbnail information
	video?: EmbedImage; // video object	video information
	provider?: {
		name?: string;
		url?: string;
	}; // provider object	provider information
	author?: {
		name?: string;
		url?: string;
		icon_url?: string;
		proxy_icon_url?: string;
	}; // author object	author information
	fields?: {
		name: string;
		value: string;
		inline?: boolean;
	}[];
}

export enum EmbedType {
	rich = "rich",
	image = "image",
	video = "video",
	gifv = "gifv",
	article = "article",
	link = "link",
}

export interface EmbedImage {
	url?: string;
	proxy_url?: string;
	height?: number;
	width?: number;
}

export interface Reaction {
	count: number;
	//// not saved in the database // me: boolean; // whether the current user reacted using this emoji
	emoji: PartialEmoji;
	user_ids: string[];
}

export interface PartialEmoji {
	id?: string;
	name: string;
	animated?: boolean;
}

export interface AllowedMentions {
	parse?: ("users" | "roles" | "everyone")[];
	roles?: string[];
	users?: string[];
	replied_user?: boolean;
}

export const Attachment = {
	id: String, // attachment id
	filename: String, // name of file attached
	size: Number, // size of file in bytes
	url: String, // source url of file
	proxy_url: String, // a proxied url of file
	height: Number, // height of file (if image)
	width: Number, // width of file (if image)
	content_type: String,
};

export const EmbedImage = {
	url: String,
	proxy_url: String,
	height: Number,
	width: Number,
};

const Reaction = {
	count: Number,
	user_ids: [String],
	emoji: {
		id: String,
		name: String,
		animated: Boolean,
	},
};

export const Embed = {
	title: String, //title of embed
	type: { type: String }, // type of embed (always "rich" for webhook embeds)
	description: String, // description of embed
	url: String, // url of embed
	timestamp: Date, // timestamp of embed content
	color: Number, // color code of the embed
	footer: {
		text: String,
		icon_url: String,
		proxy_icon_url: String,
	}, // footer object	footer information
	image: EmbedImage, // image object	image information
	thumbnail: EmbedImage, // thumbnail object	thumbnail information
	video: EmbedImage, // video object	video information
	provider: {
		name: String,
		url: String,
	}, // provider object	provider information
	author: {
		name: String,
		url: String,
		icon_url: String,
		proxy_icon_url: String,
	}, // author object	author information
	fields: [
		{
			name: String,
			value: String,
			inline: Boolean,
		},
	],
};

export const MessageSchema = new Schema({
	id: String,
	channel_id: String,
	author_id: String,
	webhook_id: String,
	guild_id: String,
	application_id: String,
	content: String,
	timestamp: Date,
	edited_timestamp: Date,
	tts: Boolean,
	mention_everyone: Boolean,
	mention_user_ids: [String],
	mention_role_ids: [String],
	mention_channel_ids: [String],
	attachments: [Attachment],
	embeds: [Embed],
	reactions: [Reaction],
	nonce: Schema.Types.Mixed, // can be a long or a string
	pinned: Boolean,
	type: { type: Number },
	activity: {
		type: { type: Number },
		party_id: String,
	},
	flags: Types.Long,
	stickers: [],
	message_reference: {
		message_id: String,
		channel_id: String,
		guild_id: String,
	},
	components: [MessageComponent],
	// virtual:
	// author: {
	// 	ref: UserModel,
	// 	localField: "author_id",
	// 	foreignField: "id",
	// 	justOne: true,
	// 	autopopulate: { select: { id: true, user_data: false } },
	// },
});

MessageSchema.virtual("author", {
	ref: UserModel,
	localField: "author_id",
	foreignField: "id",
	justOne: true,
	autopopulate: { select: PublicUserProjection },
});

MessageSchema.virtual("member", {
	ref: MemberModel,
	localField: "author_id",
	foreignField: "id",
	justOne: true,
});

MessageSchema.virtual("mentions", {
	ref: UserModel,
	localField: "mention_user_ids",
	foreignField: "id",
	justOne: false,
	autopopulate: { select: PublicUserProjection },
});

MessageSchema.virtual("mention_roles", {
	ref: RoleModel,
	localField: "mention_role_ids",
	foreignField: "id",
	justOne: false,
	autopopulate: true,
});

MessageSchema.virtual("mention_channels", {
	ref: RoleModel,
	localField: "mention_channel_ids",
	foreignField: "id",
	justOne: false,
	autopopulate: { select: { id: true, guild_id: true, type: true, name: true } },
});

MessageSchema.virtual("referenced_message", {
	ref: "Message",
	localField: "message_reference.message_id",
	foreignField: "id",
	justOne: true,
	autopopulate: true,
});

MessageSchema.virtual("created_at").get(function (this: MessageDocument) {
	return new Date(Snowflake.deconstruct(this.id).timestamp);
});

MessageSchema.set("removeResponse", ["mention_channel_ids", "mention_role_ids", "mention_user_ids", "author_id"]);

// TODO: missing Application Model
// MessageSchema.virtual("application", {
// 	ref: Application,
// 	localField: "mention_role_ids",
// 	foreignField: "id",
// 	justOne: true,
// });

// @ts-ignore
export const MessageModel = db.model<MessageDocument>("Message", MessageSchema, "messages");