twitch-clone/backend/src/module/auth/profile/profile.service.ts

143 lines
3.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { ConflictException, Injectable } from '@nestjs/common';
import * as Upload from 'graphql-upload/Upload.js';
import * as sharp from 'sharp';
import { SocialLink, User } from '@/prisma/generated';
import { PrismaService } from '@/src/core/prisma/prisma.service';
import { ChangeProfileInfoInput } from '@/src/module/auth/profile/inputs/change-profile-info.input';
import {
SocialLinkInput,
SocialLinkOrderInput,
} from '@/src/module/auth/profile/inputs/social-link.input';
import { StorageService } from '../../libs/storage/storage.service';
@Injectable()
export class ProfileService {
constructor(
private readonly prismaService: PrismaService,
private readonly storageService: StorageService,
) {
}
public async changeAvatar(user: User, file: Upload) {
if (user.avatar) {
await this.storageService.remove(user.avatar);
}
const chunks: Buffer[] = [];
for await (const chunk of file.createReadStream()) {
chunks.push(chunk);
}
const buffer = Buffer.concat(chunks);
const fileName = `/channels/${user.name}.webp`;
const processedBuffer = await sharp(buffer, { animated: file.filename.endsWith('.gif') })
.resize(512, 512)
.webp()
.toBuffer();
await this.storageService.upload(processedBuffer, fileName, 'image/webp');
await this.prismaService.user.update({
where: { id: user.id },
data: { avatar: fileName },
});
return true;
}
public async removeAvatar(user: User) {
if (!user.avatar) {
return true;
}
await this.storageService.remove(user.avatar);
await this.prismaService.user.update({
where: { id: user.id },
data: { avatar: null },
});
return true;
}
public async changeInfo(user: User, input: ChangeProfileInfoInput) {
const { bio = user.bio, displayName = user.displayName, name = user.name } = input;
const existingUser = await this.prismaService.user.findUnique({
where: { name },
});
if (existingUser && user.name !== name) {
throw new ConflictException('Пользователь с таким именем уже существует');
}
return this.prismaService.user.update({
where: { id: user.id },
data: { bio, displayName, name },
});
}
public async createSocialLink(user: User, input: SocialLinkInput) {
const { title, url } = input;
const lastSocialLink = await this.prismaService.socialLink.findFirst({
where: { userId: user.id },
orderBy: { position: 'desc' },
});
return this.prismaService.socialLink.create({
data: {
url,
title,
position: lastSocialLink ? lastSocialLink.position + 1 : 1,
user: {
connect: {
id: user.id,
},
},
},
});
}
public async findSocialLink(user: User) {
return this.prismaService.socialLink.findMany({
where: { userId: user.id },
});
}
public async reorderSocialLinks(list: SocialLinkOrderInput[]) {
if (list.length === 0) {
return;
}
const updatePromises = list.map(async (socialLink) => this.prismaService.socialLink.update({
where: { id: socialLink.id },
data: { position: Number(socialLink.position) },
}));
await Promise.all(updatePromises);
return true;
}
public async updateSocialLink(id: SocialLink['id'], input: SocialLinkInput) {
const { title, url } = input;
return this.prismaService.socialLink.update({
where: { id },
data: { title, url },
});
}
public async removeSocialLink(id: SocialLink['id']) {
await this.prismaService.socialLink.delete({
where: { id },
});
return true;
}
}