feat: better credit system to prevent spam
This commit is contained in:
parent
8285bb0ddf
commit
a214815f81
|
|
@ -1,5 +1,5 @@
|
|||
import { Global, Module } from '@nestjs/common';
|
||||
import { PrismaRepository, PrismaService } from './prisma.service';
|
||||
import { PrismaRepository, PrismaService, PrismaTransaction } from './prisma.service';
|
||||
import { OrganizationRepository } from '@gitroom/nestjs-libraries/database/prisma/organizations/organization.repository';
|
||||
import { OrganizationService } from '@gitroom/nestjs-libraries/database/prisma/organizations/organization.service';
|
||||
import { UsersService } from '@gitroom/nestjs-libraries/database/prisma/users/users.service';
|
||||
|
|
@ -49,6 +49,7 @@ import { FalService } from '@gitroom/nestjs-libraries/openai/fal.service';
|
|||
providers: [
|
||||
PrismaService,
|
||||
PrismaRepository,
|
||||
PrismaTransaction,
|
||||
UsersService,
|
||||
UsersRepository,
|
||||
OrganizationService,
|
||||
|
|
|
|||
|
|
@ -37,16 +37,17 @@ export class MediaService {
|
|||
org: Organization,
|
||||
generatePromptFirst?: boolean
|
||||
) {
|
||||
if (generatePromptFirst) {
|
||||
prompt = await this._openAi.generatePromptForPicture(prompt);
|
||||
console.log('Prompt:', prompt);
|
||||
}
|
||||
const image = await this._openAi.generateImage(
|
||||
prompt,
|
||||
!!generatePromptFirst
|
||||
return await this._subscriptionService.useCredit(
|
||||
org,
|
||||
'ai_images',
|
||||
async () => {
|
||||
if (generatePromptFirst) {
|
||||
prompt = await this._openAi.generatePromptForPicture(prompt);
|
||||
console.log('Prompt:', prompt);
|
||||
}
|
||||
return this._openAi.generateImage(prompt, !!generatePromptFirst);
|
||||
}
|
||||
);
|
||||
await this._subscriptionService.useCredit(org);
|
||||
return image;
|
||||
}
|
||||
|
||||
saveFile(org: string, fileName: string, filePath: string) {
|
||||
|
|
@ -99,17 +100,21 @@ export class MediaService {
|
|||
throw new HttpException('This video is not available in trial mode', 406);
|
||||
}
|
||||
|
||||
const loadedData = await video.instance.processAndValidate(
|
||||
body.output,
|
||||
body.customParams
|
||||
await video.instance.processAndValidate(body.customParams);
|
||||
|
||||
return await this._subscriptionService.useCredit(
|
||||
org,
|
||||
'ai_videos',
|
||||
async () => {
|
||||
const loadedData = await video.instance.process(
|
||||
body.output,
|
||||
body.customParams
|
||||
);
|
||||
|
||||
const file = await this.storage.uploadSimple(loadedData);
|
||||
return this.saveFile(org.id, file.split('/').pop(), file);
|
||||
}
|
||||
);
|
||||
|
||||
const file = await this.storage.uploadSimple(loadedData);
|
||||
const save = await this.saveFile(org.id, file.split('/').pop(), file);
|
||||
|
||||
await this._subscriptionService.useCredit(org, 'ai_videos');
|
||||
|
||||
return save;
|
||||
}
|
||||
|
||||
async videoFunction(identifier: string, functionName: string, body: any) {
|
||||
|
|
|
|||
|
|
@ -25,3 +25,12 @@ export class PrismaRepository<T extends keyof PrismaService> {
|
|||
this.model = this._prismaService;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class PrismaTransaction {
|
||||
public model: Pick<PrismaService, '$transaction'>;
|
||||
constructor(private _prismaService: PrismaService) {
|
||||
this.model = this._prismaService;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { PrismaRepository } from '@gitroom/nestjs-libraries/database/prisma/prisma.service';
|
||||
import {
|
||||
PrismaRepository,
|
||||
PrismaTransaction,
|
||||
} from '@gitroom/nestjs-libraries/database/prisma/prisma.service';
|
||||
import dayjs from 'dayjs';
|
||||
import { Organization } from '@prisma/client';
|
||||
|
||||
|
|
@ -203,7 +206,11 @@ export class SubscriptionRepository {
|
|||
});
|
||||
}
|
||||
|
||||
async getCreditsFrom(organizationId: string, from: dayjs.Dayjs, type = 'ai_images') {
|
||||
async getCreditsFrom(
|
||||
organizationId: string,
|
||||
from: dayjs.Dayjs,
|
||||
type = 'ai_images'
|
||||
) {
|
||||
const load = await this._credits.model.credits.groupBy({
|
||||
by: ['organizationId'],
|
||||
where: {
|
||||
|
|
@ -221,14 +228,29 @@ export class SubscriptionRepository {
|
|||
return load?.[0]?._sum?.credits || 0;
|
||||
}
|
||||
|
||||
useCredit(org: Organization, type = 'ai_images') {
|
||||
return this._credits.model.credits.create({
|
||||
async useCredit<T>(
|
||||
org: Organization,
|
||||
type = 'ai_images',
|
||||
func: () => Promise<T>
|
||||
) {
|
||||
const data = await this._credits.model.credits.create({
|
||||
data: {
|
||||
organizationId: org.id,
|
||||
credits: 1,
|
||||
type,
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
return await func();
|
||||
} catch (err) {
|
||||
await this._credits.model.credits.delete({
|
||||
where: {
|
||||
id: data.id,
|
||||
},
|
||||
});
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
setCustomerId(orgId: string, customerId: string) {
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ export class SubscriptionService {
|
|||
);
|
||||
}
|
||||
|
||||
useCredit(organization: Organization, type = 'ai_images') {
|
||||
return this._subscriptionRepository.useCredit(organization, type);
|
||||
useCredit<T>(organization: Organization, type = 'ai_images', func: () => Promise<T>) : Promise<T> {
|
||||
return this._subscriptionRepository.useCredit(organization, type, func);
|
||||
}
|
||||
|
||||
getCode(code: string) {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ export abstract class VideoAbstract<T> {
|
|||
dto: Type<T>;
|
||||
|
||||
async processAndValidate(
|
||||
output: 'vertical' | 'horizontal',
|
||||
customParams?: T
|
||||
) {
|
||||
const validationPipe = new ValidationPipe({
|
||||
|
|
@ -17,15 +16,13 @@ export abstract class VideoAbstract<T> {
|
|||
},
|
||||
});
|
||||
|
||||
const transformed = await validationPipe.transform(customParams, {
|
||||
await validationPipe.transform(customParams, {
|
||||
type: 'body',
|
||||
metatype: this.dto,
|
||||
});
|
||||
|
||||
return this.process(output, transformed);
|
||||
}
|
||||
|
||||
protected abstract process(
|
||||
abstract process(
|
||||
output: 'vertical' | 'horizontal',
|
||||
customParams?: T
|
||||
): Promise<URL>;
|
||||
|
|
|
|||
Loading…
Reference in New Issue