86 lines
2.6 KiB
TypeScript
86 lines
2.6 KiB
TypeScript
import { ForbiddenException, Injectable, NotFoundException } from '@nestjs/common';
|
|
import { eq } from 'drizzle-orm';
|
|
import { DrizzleService } from '../../database/drizzle.service';
|
|
import { profile, profileMedia } from '../../database/schema';
|
|
import { StorageService } from '../../storage/storage.service';
|
|
|
|
@Injectable()
|
|
export class MediaService {
|
|
constructor(
|
|
private readonly drizzleService: DrizzleService,
|
|
private readonly storageService: StorageService,
|
|
) {}
|
|
|
|
async upload(
|
|
userId: string,
|
|
profileId: string,
|
|
file: { buffer: Buffer; originalname: string; mimetype: string },
|
|
type: 'photo' | 'video' | 'audio',
|
|
) {
|
|
await this.assertOwnership(userId, profileId);
|
|
|
|
const folder = type;
|
|
const objectName = await this.storageService.uploadFile(
|
|
file.buffer,
|
|
file.originalname,
|
|
file.mimetype,
|
|
folder,
|
|
);
|
|
const path = this.storageService.getPublicUrl(objectName);
|
|
|
|
const existing = await this.drizzleService.db
|
|
.select({ sortOrder: profileMedia.sortOrder })
|
|
.from(profileMedia)
|
|
.where(eq(profileMedia.profileId, profileId))
|
|
.orderBy(profileMedia.sortOrder);
|
|
|
|
const nextOrder = existing.length > 0
|
|
? (existing[existing.length - 1].sortOrder ?? 0) + 1
|
|
: 0;
|
|
|
|
const [newMedia] = await this.drizzleService.db
|
|
.insert(profileMedia)
|
|
.values({ profileId, path, type, sortOrder: nextOrder } as any)
|
|
.returning();
|
|
|
|
return newMedia;
|
|
}
|
|
|
|
async getByProfileId(profileId: string) {
|
|
return this.drizzleService.db
|
|
.select()
|
|
.from(profileMedia)
|
|
.where(eq(profileMedia.profileId, profileId))
|
|
.orderBy(profileMedia.sortOrder);
|
|
}
|
|
|
|
async delete(userId: string, mediaId: string) {
|
|
const [found] = await this.drizzleService.db
|
|
.select()
|
|
.from(profileMedia)
|
|
.where(eq(profileMedia.id, mediaId))
|
|
.limit(1);
|
|
|
|
if (!found) throw new NotFoundException('Media not found');
|
|
|
|
await this.assertOwnership(userId, found.profileId);
|
|
|
|
const objectName = found.path.split('/').slice(-2).join('/');
|
|
await this.storageService.deleteFile(objectName).catch(() => {});
|
|
await this.drizzleService.db.delete(profileMedia).where(eq(profileMedia.id, mediaId));
|
|
|
|
return { message: 'Media deleted' };
|
|
}
|
|
|
|
private async assertOwnership(userId: string, profileId: string) {
|
|
const [found] = await this.drizzleService.db
|
|
.select({ userId: profile.userId })
|
|
.from(profile)
|
|
.where(eq(profile.id, profileId))
|
|
.limit(1);
|
|
|
|
if (!found) throw new NotFoundException('Profile not found');
|
|
if (found.userId !== userId) throw new ForbiddenException('Profile does not belong to you');
|
|
}
|
|
}
|