import { CommentState } from "../types/comments";
import Snowflake from "./snowflake";
import Animation, { BasicAnimation } from "./animation";
import User from "./user";
import { UserType } from "../types/basicUser";
import { SnowflakeResolvable } from "../types/snowflake";
import { RequestContext } from "./requestContext";
import {
DBComment, DBCommentFull, DBCommentWithAnimation, DBCommentWithAuthor, prisma
} from "../../prisma";
/**
* Comment data holder
*/
class Comment {
id: Snowflake;
ctx: RequestContext;
animation: BasicAnimation;
user: User;
content: string;
state: CommentState;
reported?: boolean;
/**
* @param {object} data
*/
constructor({
id,
ctx,
animation,
user,
content,
state,
reported
}: {
id: Snowflake,
ctx: RequestContext,
animation: BasicAnimation,
user: User,
content: string,
state: CommentState,
reported?: boolean
}) {
this.id = id;
this.ctx = ctx;
this.animation = animation;
this.user = user;
this.content = content;
this.state = state;
this.reported = reported;
}
/**
* @param {any} data
* @param {RequestContext} ctx
* @return {Promise<Comment>}
*/
static async fromDatabase(
data: (DBComment | DBCommentFull | DBCommentWithAnimation | DBCommentWithAuthor) &
{ reported?: boolean },
ctx: RequestContext
): Promise<Comment> {
return new Comment({
ctx,
id: new Snowflake(data.snowflake),
animation: "animation" in data ?
await Animation.fromDatabase(data.animation, ctx) :
await Animation.getAnimation(data.animationId, ctx),
user: "author" in data ?
await User.fromDatabase(data.author, ctx) :
await User.getUser(data.authorId, ctx),
content: data.content,
state: data.state,
reported: "reported" in data ? data.reported : undefined
});
}
/**
* @param {SnowflakeResolvable} id
* @param {RequestContext} ctx
* @return {Promise<Comment>}
*/
static async getComment(id: SnowflakeResolvable, ctx: RequestContext):
Promise<Comment> {
const res = await prisma.comment.findUniqueOrThrow({
where: {
snowflake: (new Snowflake(id)).toBigInt()
},
include: {
animation: true,
author: true
}
});
const comment = await Comment.fromDatabase(res, ctx);
if(
comment.state !== CommentState.NORMAL &&
!ctx.client?.user.comparePosition(UserType.MODERATOR)
) {
throw new Error("deleted");
}
if(ctx.user) {
const reported = await prisma.modQueue.findFirst({
where: {
resourceId: (new Snowflake(id)).toBigInt(),
reporterId: ctx.user.id.toBigInt()
}
});
comment.reported = reported !== null;
}
return comment;
}
/**
* Updates comment data
* @return {Promise<void>}
*/
async update(): Promise<void> {
if(!this.ctx.client) throw new Error("unauthorized");
if(!this.ctx.client.user.comparePosition(UserType.MODERATOR)) {
throw new Error("unauthorized");
}
await prisma.comment.update({
where: {
snowflake: this.id.toBigInt()
},
data: {
content: this.content,
state: this.state
}
});
}
/**
* Deletes comment
* @return {Promise<void>}
*/
delete(): Promise<void> {
if(!this.ctx.client) throw new Error("unauthorized");
if(!this.ctx.client.user.comparePosition(UserType.MODERATOR)) {
throw new Error("unauthorized");
}
if(this.state !== CommentState.NORMAL) throw new Error("already_deleted");
this.state = CommentState.MODERATOR_DELETED;
return this.update();
}
/**
* Creates a JSON-compatible object
* @return {Object}
*/
toJSON() {
return {
id: this.id.getSnowflake(),
sent: this.id.time,
user: this.user.toJSON(),
animation: this.animation.id.toString(),
content: this.content,
state: this.state,
reported: this.reported
};
}
}
export default Comment;
Source