2024-10-24 17:20:00 +02:00
|
|
|
import { RolePermission } from "@versia/client/types";
|
2024-10-24 17:31:39 +02:00
|
|
|
import type { Delete, LikeExtension } from "@versia/federation/types";
|
2024-11-01 21:05:54 +01:00
|
|
|
import { db } from "@versia/kit/db";
|
|
|
|
|
import { Likes } from "@versia/kit/tables";
|
2024-10-24 17:20:00 +02:00
|
|
|
import {
|
|
|
|
|
type InferInsertModel,
|
|
|
|
|
type InferSelectModel,
|
|
|
|
|
type SQL,
|
|
|
|
|
desc,
|
|
|
|
|
eq,
|
|
|
|
|
inArray,
|
|
|
|
|
} from "drizzle-orm";
|
|
|
|
|
import { z } from "zod";
|
|
|
|
|
import { config } from "~/packages/config-manager/index.ts";
|
|
|
|
|
import type { Status } from "../functions/status.ts";
|
|
|
|
|
import type { UserType } from "../functions/user.ts";
|
|
|
|
|
import { BaseInterface } from "./base.ts";
|
|
|
|
|
import { Note } from "./note.ts";
|
|
|
|
|
import { User } from "./user.ts";
|
|
|
|
|
|
|
|
|
|
export type LikeType = InferSelectModel<typeof Likes> & {
|
|
|
|
|
liker: UserType;
|
|
|
|
|
liked: Status;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export class Like extends BaseInterface<typeof Likes, LikeType> {
|
2024-11-01 21:20:12 +01:00
|
|
|
public static schema = z.object({
|
2024-10-24 17:20:00 +02:00
|
|
|
id: z.string(),
|
|
|
|
|
name: z.string(),
|
|
|
|
|
permissions: z.array(z.nativeEnum(RolePermission)),
|
|
|
|
|
priority: z.number(),
|
|
|
|
|
description: z.string().nullable(),
|
|
|
|
|
visible: z.boolean(),
|
|
|
|
|
icon: z.string().nullable(),
|
|
|
|
|
});
|
|
|
|
|
|
2024-11-01 21:20:12 +01:00
|
|
|
public async reload(): Promise<void> {
|
2024-10-24 17:20:00 +02:00
|
|
|
const reloaded = await Like.fromId(this.data.id);
|
|
|
|
|
|
|
|
|
|
if (!reloaded) {
|
|
|
|
|
throw new Error("Failed to reload like");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.data = reloaded.data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static async fromId(id: string | null): Promise<Like | null> {
|
|
|
|
|
if (!id) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return await Like.fromSql(eq(Likes.id, id));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static async fromIds(ids: string[]): Promise<Like[]> {
|
|
|
|
|
return await Like.manyFromSql(inArray(Likes.id, ids));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static async fromSql(
|
|
|
|
|
sql: SQL<unknown> | undefined,
|
|
|
|
|
orderBy: SQL<unknown> | undefined = desc(Likes.id),
|
|
|
|
|
) {
|
|
|
|
|
const found = await db.query.Likes.findFirst({
|
|
|
|
|
where: sql,
|
|
|
|
|
orderBy,
|
|
|
|
|
with: {
|
|
|
|
|
liked: true,
|
|
|
|
|
liker: true,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!found) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
return new Like(found);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static async manyFromSql(
|
|
|
|
|
sql: SQL<unknown> | undefined,
|
|
|
|
|
orderBy: SQL<unknown> | undefined = desc(Likes.id),
|
|
|
|
|
limit?: number,
|
|
|
|
|
offset?: number,
|
|
|
|
|
extra?: Parameters<typeof db.query.Likes.findMany>[0],
|
|
|
|
|
) {
|
|
|
|
|
const found = await db.query.Likes.findMany({
|
|
|
|
|
where: sql,
|
|
|
|
|
orderBy,
|
|
|
|
|
limit,
|
|
|
|
|
offset,
|
|
|
|
|
with: {
|
|
|
|
|
liked: true,
|
|
|
|
|
liker: true,
|
|
|
|
|
...extra?.with,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return found.map((s) => new Like(s));
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-01 21:20:12 +01:00
|
|
|
public async update(newRole: Partial<LikeType>): Promise<LikeType> {
|
2024-10-24 17:20:00 +02:00
|
|
|
await db.update(Likes).set(newRole).where(eq(Likes.id, this.id));
|
|
|
|
|
|
|
|
|
|
const updated = await Like.fromId(this.data.id);
|
|
|
|
|
|
|
|
|
|
if (!updated) {
|
|
|
|
|
throw new Error("Failed to update like");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return updated.data;
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-01 21:20:12 +01:00
|
|
|
public save(): Promise<LikeType> {
|
2024-10-24 17:20:00 +02:00
|
|
|
return this.update(this.data);
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-01 21:20:12 +01:00
|
|
|
public async delete(ids?: string[]): Promise<void> {
|
2024-10-24 17:20:00 +02:00
|
|
|
if (Array.isArray(ids)) {
|
|
|
|
|
await db.delete(Likes).where(inArray(Likes.id, ids));
|
|
|
|
|
} else {
|
|
|
|
|
await db.delete(Likes).where(eq(Likes.id, this.id));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static async insert(
|
|
|
|
|
data: InferInsertModel<typeof Likes>,
|
|
|
|
|
): Promise<Like> {
|
|
|
|
|
const inserted = (await db.insert(Likes).values(data).returning())[0];
|
|
|
|
|
|
|
|
|
|
const role = await Like.fromId(inserted.id);
|
|
|
|
|
|
|
|
|
|
if (!role) {
|
|
|
|
|
throw new Error("Failed to insert like");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return role;
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-01 21:20:12 +01:00
|
|
|
public get id() {
|
2024-10-24 17:20:00 +02:00
|
|
|
return this.data.id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public getUri(): URL {
|
|
|
|
|
return new URL(`/objects/${this.data.id}`, config.http.base_url);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public toVersia(): LikeExtension {
|
|
|
|
|
return {
|
|
|
|
|
id: this.data.id,
|
|
|
|
|
author: User.getUri(
|
|
|
|
|
this.data.liker.id,
|
|
|
|
|
this.data.liker.uri,
|
|
|
|
|
config.http.base_url,
|
|
|
|
|
),
|
|
|
|
|
type: "pub.versia:likes/Like",
|
|
|
|
|
created_at: new Date(this.data.createdAt).toISOString(),
|
|
|
|
|
liked: Note.getUri(
|
|
|
|
|
this.data.liked.id,
|
|
|
|
|
this.data.liked.uri,
|
|
|
|
|
) as string,
|
|
|
|
|
uri: this.getUri().toString(),
|
|
|
|
|
};
|
|
|
|
|
}
|
2024-10-24 17:31:39 +02:00
|
|
|
|
|
|
|
|
public unlikeToVersia(unliker?: User): Delete {
|
|
|
|
|
return {
|
|
|
|
|
type: "Delete",
|
|
|
|
|
id: crypto.randomUUID(),
|
|
|
|
|
created_at: new Date().toISOString(),
|
|
|
|
|
author: User.getUri(
|
|
|
|
|
unliker?.id ?? this.data.liker.id,
|
|
|
|
|
unliker?.data.uri ?? this.data.liker.uri,
|
|
|
|
|
config.http.base_url,
|
|
|
|
|
),
|
|
|
|
|
deleted_type: "pub.versia:likes/Like",
|
|
|
|
|
deleted: this.getUri().toString(),
|
|
|
|
|
};
|
|
|
|
|
}
|
2024-10-24 17:20:00 +02:00
|
|
|
}
|