diff --git a/src/api/util/handlers/Message.ts b/src/api/util/handlers/Message.ts
index 2ff56a7a..97040fd3 100644
--- a/src/api/util/handlers/Message.ts
+++ b/src/api/util/handlers/Message.ts
@@ -486,7 +486,7 @@ export async function postHandleMessage(message: Message) {
const content = message.content?.replace(/ *`[^)]*` */g, ""); // remove markdown
const linkMatches = content?.match(LINK_REGEX) || [];
-
+ message.clean_data();
const data = { ...message };
const currentNormalizedUrls = new Set<string>();
diff --git a/src/util/entities/BaseClass.ts b/src/util/entities/BaseClass.ts
index 1aaf1479..a8844630 100644
--- a/src/util/entities/BaseClass.ts
+++ b/src/util/entities/BaseClass.ts
@@ -20,12 +20,40 @@ import { BaseEntity, BeforeInsert, BeforeUpdate, Column, ColumnOptions, FindOpti
import { Snowflake } from "../util/Snowflake";
import { getDatabase } from "../util/Database";
import { OrmUtils } from "../imports/OrmUtils";
+import { annotationsKey } from "../util/Decorators";
export class BaseClassWithoutId extends BaseEntity {
private get construct() {
return this.constructor;
}
+ // stores custom annotations we may stick on the properties
+ [annotationsKey]: { [p: string]: string[] };
+
+ // retrieves the custom annotations as its not super straight forward
+ get_annotations() {
+ return Object.getPrototypeOf(this)[annotationsKey];
+ }
+
+ // Loops through all the keys and compares it to annotations. If the RemoveEmpty is there it sets the value to undefined if null
+ clean_data() {
+ const annotations = this.get_annotations();
+ for (const key in this) {
+ if (
+ key in this && // This object has this property, should never fail but better to be safe
+ key in annotations && // If this property has an annotation
+ annotations[key].indexOf("JsonRemoveEmpty") > -1 && // if one of the annotations is JsonRemoveEmpty
+ (this[key] == null || // If this property is null
+ (typeof this[key] == "object" && Object.keys(this[key]).length == 0))
+ ) {
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-expect-error
+ this[key] = undefined; // set to undefined to remove
+ }
+ }
+ return this;
+ }
+
private get metadata() {
return getDatabase()?.getMetadata(this.construct);
}
diff --git a/src/util/entities/Message.ts b/src/util/entities/Message.ts
index 71364673..a54ab7d5 100644
--- a/src/util/entities/Message.ts
+++ b/src/util/entities/Message.ts
@@ -31,6 +31,7 @@ import { Attachment } from "./Attachment";
import { NewUrlUserSignatureData } from "../Signing";
import { ActionRowComponent, ApplicationCommandType, Embed, MessageSnapshot, MessageType, PartialMessage, Poll, Reaction } from "@spacebar/schemas";
import { MessageFlags } from "@spacebar/util";
+import { JsonRemoveEmpty } from "../util/Decorators";
@Entity({
name: "messages",
@@ -122,14 +123,17 @@ export class Message extends BaseClass {
mention_everyone?: boolean;
@JoinTable({ name: "message_user_mentions" })
+ @JsonRemoveEmpty
@ManyToMany(() => User)
mentions: User[];
@JoinTable({ name: "message_role_mentions" })
+ @JsonRemoveEmpty
@ManyToMany(() => Role)
mention_roles: Role[];
@JoinTable({ name: "message_channel_mentions" })
+ @JsonRemoveEmpty
@ManyToMany(() => Channel)
mention_channels: Channel[];
@@ -141,12 +145,15 @@ export class Message extends BaseClass {
cascade: true,
orphanedRowAction: "delete",
})
+ @JsonRemoveEmpty
attachments?: Attachment[];
@Column({ type: "simple-json" })
+ @JsonRemoveEmpty
embeds: Embed[];
@Column({ type: "simple-json" })
+ @JsonRemoveEmpty
reactions: Reaction[];
@Column({ type: "text", nullable: true })
@@ -201,9 +208,11 @@ export class Message extends BaseClass {
};
@Column({ type: "simple-json", nullable: true })
+ @JsonRemoveEmpty
components?: ActionRowComponent[];
@Column({ type: "simple-json", nullable: true })
+ @JsonRemoveEmpty
poll?: Poll;
@Column({ nullable: true })
diff --git a/src/util/util/Decorators.ts b/src/util/util/Decorators.ts
new file mode 100644
index 00000000..9de9c1c9
--- /dev/null
+++ b/src/util/util/Decorators.ts
@@ -0,0 +1,21 @@
+import { BaseClassWithoutId } from "@spacebar/util*";
+
+export const annotationsKey = Symbol("Annotations");
+
+// Generates an array using the annotationsKey as a property on a class when annotated with the below decorators
+export function initAnnotationMetadata(target: BaseClassWithoutId, propertyKey: string) {
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions
+ target[annotationsKey] || (target[annotationsKey] = {});
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions
+ target[annotationsKey][propertyKey] || (target[annotationsKey][propertyKey] = []);
+}
+
+// Adds to the generated array on the class with the annotation added.
+export function addAnnotationMetadata(target: BaseClassWithoutId, propertyKey: string, annotation: string) {
+ target[annotationsKey] = { ...target[annotationsKey], [propertyKey]: [...target[annotationsKey][propertyKey], annotation] };
+}
+
+export function JsonRemoveEmpty(target: BaseClassWithoutId, propertyKey: string) {
+ initAnnotationMetadata(target, propertyKey);
+ addAnnotationMetadata(target, propertyKey, "JsonRemoveEmpty");
+}
|