369 lines
8.4 KiB
TypeScript
369 lines
8.4 KiB
TypeScript
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");
|