import Snowflake from "./snowflake";
import { UserType } from "../types/basicUser";
import User from "./user";
import UserClient from "./userClient";
import Collection from "@discordjs/collection";
import { SnowflakeString } from "../types/snowflake";
import { RequestContext } from "./requestContext";
import {
DBSystemRelation, DBSystemRelationAuthor, DBSystemRelationFull, DBSystemRelationTarget, prisma
} from "../../prisma";
/**
* Holds data about system - user relation
*/
class SystemRelation {
id: Snowflake;
ctx: RequestContext;
type: UserType;
target: User;
author: User;
/**
* Creates new system relation data
* @param {Object} data
*/
constructor({
id,
ctx,
type,
target,
author
}: {
id: Snowflake,
ctx: RequestContext,
type: UserType,
target: User,
author: User
}) {
this.id = id;
this.ctx = ctx;
this.type = type;
this.target = target;
this.author = author;
}
/**
* Creates object from database
* @param {DBSystemRelation | DBSystemRelationAuthor |
* DBSystemRelationTarget | DBSystemRelationFull} data
* @param {RequestContext} ctx
* @return {SystemRelation}
*/
static async fromDatabase(data: DBSystemRelation | DBSystemRelationAuthor |
DBSystemRelationTarget | DBSystemRelationFull, ctx: RequestContext) {
return new SystemRelation({
id: new Snowflake(data.snowflake),
ctx,
type: data.type,
target: "target" in data ? await User.fromDatabase(data.target, ctx) :
await User.getUser(data.targetId, ctx),
author: "author" in data ? await User.fromDatabase(data.author, ctx) :
await User.getUser(data.authorId, ctx)
});
}
/**
* Updates relation
* @param {UserType} type
* @return {Promise<SystemRelation>}
*/
async updateRelation(type: UserType): Promise<SystemRelation> {
if(!this.ctx.hasClient()) throw new Error("Client required for relation updates");
return await SystemRelation.createRelation(this.ctx, this.target, type);
}
/**
* Creates or updates relation
* @param {RequestContext} ctx
* @param {User} target
* @param {UserType} type
* @deprecated
*/
static async upsertRelation(ctx: RequestContext, target: User, type: UserType):
Promise<never> {
if(!ctx.hasClient()) throw new Error("Client required for relation updates");
throw new Error("upsertRelation is deprecated, use createRelation instead");
}
/**
* Creates relation
* @param {RequestContext} ctx
* @param {User} target
* @param {UserType} type
* @param {Pool} conn
* @return {Promise<SystemRelation>}
*/
static async createRelation(ctx: RequestContext, target: User, type: UserType):
Promise<SystemRelation> {
if(!ctx.hasClient()) throw new Error("Client required for relation updates");
const data = await prisma.systemRelation.create({
data: {
snowflake: Snowflake.newSnowflake().toBigInt(),
type,
author: {
connect: {
snowflake: ctx.client.user.id.toBigInt()
}
},
target: {
connect: {
snowflake: target.id.toBigInt()
}
}
}
});
return await SystemRelation.fromDatabase(data, ctx);
}
/**
* Gets current system relation
* @param {User} target user
* @param {RequestContext} ctx
* @param {UserClient} client
* @return {Promise<SystemRelation|null>} Systerm relation or null if default
*/
static async getRelation(target: User, ctx: RequestContext, client?: UserClient):
Promise<SystemRelation|null> {
const data = await prisma.systemRelation.findFirst({
where: {
targetId: target.id.toBigInt()
},
orderBy: {
snowflake: "desc"
}
});
if(!data) return null;
return await SystemRelation.fromDatabase(data, ctx);
}
/**
* Gets all (even past) relations. Limits to 150.
* @param {User} target
* @param {RequestContext} ctx
* @return {Promise<Collection<SystemRelation>>}
*/
static async getRelations(target: User, ctx: RequestContext):
Promise<Collection<SnowflakeString, SystemRelation>> {
const data = await prisma.systemRelation.findMany({
where: {
targetId: target.id.toBigInt()
},
orderBy: {
snowflake: "desc"
},
take: 150
});
var col = new Collection<SnowflakeString, SystemRelation>();
for(var rel of data) {
col.set(rel.snowflake.toString(), await SystemRelation.fromDatabase(rel, ctx));
}
return col;
}
/**
* Creates a JSON-compatible object
* @return {Object}
*/
toJSON() {
return {
id: this.id.getSnowflake(),
type: this.type,
author: this.author.toJSON(),
target: this.target.toJSON()
};
}
}
export default SystemRelation;
Source