import { UserRelationType } from "../types/userRelation";
import Snowflake from "./snowflake";
import User from "./user";
import { UserType } from "../types/basicUser";
import { RequestContext, RequestContextWithClient } from "./requestContext";
import {
DBUserRelation, DBUserRelationAuthor, DBUserRelationFull, DBUserRelationTarget, prisma
} from "../../prisma";
/**
* Holds data about user - user relation
*/
class UserRelation {
id: Snowflake;
ctx: RequestContext;
author: User;
target: User;
type: UserRelationType;
/**
* creates new user-user relation data holder
* @param {object} data
*/
constructor({
id,
ctx,
author,
target,
type
}: {
id: Snowflake,
ctx: RequestContext,
author: User,
target: User,
type: UserRelationType
}) {
this.id = id;
this.ctx = ctx;
this.author = author;
this.target = target;
this.type = type;
}
/**
* @param {DBUserRelation | DBUserRelationAuthor
* | DBUserRelationFull | DBUserRelationTarget} data
* @param {RequestContext} ctx
* @return {Promise<UserRelation>}
*/
static async fromDatabase(
data: DBUserRelation | DBUserRelationAuthor | DBUserRelationFull | DBUserRelationTarget,
ctx: RequestContext) {
return new UserRelation({
id: new Snowflake(data.snowflake),
ctx,
author: "author" in data ? await User.fromDatabase(data.author, ctx) :
await User.getUser(data.authorId, ctx),
target: "target" in data ? await User.fromDatabase(data.target, ctx) :
await User.getUser(data.targetId, ctx),
type: data.type
});
}
/**
* Loads user relation
* @param {User} target
* @param {RequestContextWithClient} ctx
* @return {Promise<UserRelation>}
*/
static async load(target: User, ctx: RequestContextWithClient): Promise<UserRelation> {
const res = await prisma.userRelation.findFirstOrThrow({
where: {
authorId: ctx.client.user.id.toBigInt(),
targetId: target.id.toBigInt()
}
});
return UserRelation.fromDatabase(res, ctx);
}
/**
* Creates or updates a relation
*
* @param {User} target
* @param {UserRelationType} type
* @param {RequestContextWithClient} ctx
* @return {Promise<UserRelation>}
* @throws {Error} if client is not set
*/
static async upsert(target: User, type: UserRelationType, ctx: RequestContextWithClient):
Promise<UserRelation> {
if(!ctx.client) throw new Error("perms");
if(ctx.client.user.id.getSnowflake() !== target.id.getSnowflake()) {
if(!ctx.client.user.comparePosition(UserType.MODERATOR)) {
throw new Error("perms");
}
}
const data = await prisma.userRelation.upsert({
where: {
authorId_targetId: {
authorId: ctx.client.user.id.toBigInt(),
targetId: target.id.toBigInt()
}
},
update: {
type
},
create: {
snowflake: Snowflake.newSnowflake().toBigInt(),
authorId: ctx.client.user.id.toBigInt(),
targetId: target.id.toBigInt(),
type
}
});
return UserRelation.fromDatabase(data, ctx);
}
/**
* Updates user relation
* @return {Promise<void>}
*/
async update(): Promise<void> {
if(!this.ctx.client) throw new Error("perms");
if(this.ctx.client.user.id.getSnowflake() !== this.author.id.getSnowflake()) {
if(!this.ctx.client.user.comparePosition(UserType.MODERATOR)) {
throw new Error("perms");
}
}
await prisma.userRelation.update({
where: {
snowflake: this.id.toBigInt()
},
data: {
type: this.type
}
});
}
/**
* Deletes user relation
* @return {Promise<void>}
*/
async delete(): Promise<void> {
if(!this.ctx.client) throw new Error("perms");
if(this.ctx.client.user.id.getSnowflake() !== this.author.id.getSnowflake()) {
if(!this.ctx.client.user.comparePosition(UserType.MODERATOR)) {
throw new Error("perms");
}
}
await prisma.userRelation.delete({
where: {
snowflake: this.id.toBigInt()
}
});
}
/**
* Creates a JSON-compatible object
* @return {Object}
*/
toJSON() {
return {
id: this.id.getSnowflake(),
author: this.author.toJSON(),
target: this.target.toJSON(),
type: this.type
};
}
}
export default UserRelation;
Source