From 95a092cec9cf5e0ea8d85922d95976ec34a0cf81 Mon Sep 17 00:00:00 2001 From: Ly Tuan Kiet Date: Sat, 9 Nov 2024 18:44:35 +0700 Subject: [PATCH] =?UTF-8?q?=F0=9F=98=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- compose.yaml | 1 + src/Message/message.schema.ts | 37 ++++++++++++++++++++++++++++--- src/User/user.module.ts | 3 +++ src/User/user.schema.ts | 23 ++++++++++++++++++- src/common/pubsub/pubsub-event.ts | 1 + 5 files changed, 61 insertions(+), 4 deletions(-) diff --git a/compose.yaml b/compose.yaml index 4f59375..b513c6f 100644 --- a/compose.yaml +++ b/compose.yaml @@ -30,6 +30,7 @@ services: - PAYOS_CHECKSUM_KEY=0b82fe148ab98083d471997df5cdd08f3c383013f8bc85e87d7ab1ab4433614e - PAYOS_WEBHOOK_URL=https://api.epess.org/v1/payos/webhook - PAYOS_BASE_URL=https://api-merchant.payos.vn/v2 + - PAYOS_RETURN_URL=https://epess.org/services//checkout - MAILU_FROM=no-reply@mail.epess.org - MAILU_HOST=10.0.27.1 - MAILU_PORT=25 diff --git a/src/Message/message.schema.ts b/src/Message/message.schema.ts index a5e5f9f..7630714 100644 --- a/src/Message/message.schema.ts +++ b/src/Message/message.schema.ts @@ -7,7 +7,12 @@ import { } from '@smatch-corp/nestjs-pothos' import { Builder, SchemaContext } from '../Graphql/graphql.builder' import { PrismaService } from '../Prisma/prisma.service' -import { Message, MessageContextType, MessageType } from '@prisma/client' +import { + ChatRoomType, + Message, + MessageContextType, + MessageType, +} from '@prisma/client' import { DateTimeUtils } from '../common/utils/datetime.utils' import { PubSubEvent } from '../common/pubsub/pubsub-event' @@ -139,6 +144,25 @@ export class MessageSchema extends PothosSchema { if (!args.input.sender) { throw new Error('Cannot get sender from context') } + let userIds: string[] = [] + // get the recipient if messageContext is CHAT + if (messageContext === MessageContextType.CHAT) { + // get chatRoomId from input + const chatRoomId = args.input.chatRoom?.connect?.id + if (!chatRoomId) { + throw new Error('Cannot get chatRoomId from input') + } + // if chatroom type is SUPPORT, user 1 is mentorId, user 2 is customerId + // query the chatRoom to get the userIds + const chatRoom = await this.prisma.chatRoom.findUnique({ + where: { + id: chatRoomId, + }, + }) + if (chatRoom?.type === ChatRoomType.SUPPORT) { + userIds = [chatRoom.mentorId!, chatRoom.customerId!] + } + } // check if content is empty if (!args.input.content || args.input.content.trim() === '') { throw new Error('Content cannot be empty') @@ -156,6 +180,13 @@ export class MessageSchema extends PothosSchema { `${PubSubEvent.MESSAGE_SENT}.${message.chatRoomId}`, message, ) + // publish to new message subscribers + userIds.forEach((userId: string) => { + ctx.http.pubSub.publish( + `${PubSubEvent.NEW_MESSAGE}.${userId}`, + message, + ) + }) return message }, }), @@ -176,9 +207,9 @@ export class MessageSchema extends PothosSchema { const { websocket: { pubSub }, } = ctx - return pubSub.asyncIterator( + return pubSub.asyncIterator([ `${PubSubEvent.MESSAGE_SENT}.${args.chatRoomId}`, - ) as unknown as AsyncIterable + ]) as unknown as AsyncIterable }, resolve: (payload: Message) => payload, }), diff --git a/src/User/user.module.ts b/src/User/user.module.ts index 4f0856a..c5079d1 100644 --- a/src/User/user.module.ts +++ b/src/User/user.module.ts @@ -1,6 +1,9 @@ import { Module } from '@nestjs/common' import { UserSchema } from './user.schema' +import { MessageModule } from '../Message/message.module' + @Module({ + imports: [MessageModule], providers: [UserSchema], exports: [UserSchema], }) diff --git a/src/User/user.schema.ts b/src/User/user.schema.ts index 6536228..a2b1d7f 100644 --- a/src/User/user.schema.ts +++ b/src/User/user.schema.ts @@ -5,17 +5,21 @@ import { PothosSchema, SchemaBuilderToken, } from '@smatch-corp/nestjs-pothos' -import { Builder } from '../Graphql/graphql.builder' +import { Builder, SchemaContext } from '../Graphql/graphql.builder' import { PrismaService } from '../Prisma/prisma.service' import { clerkClient } from '@clerk/express' import { UnauthorizedException } from '@nestjs/common' import { MailService } from '../Mail/mail.service' +import { MessageSchema } from 'src/Message/message.schema' +import { Message } from '@prisma/client' +import { PubSubEvent } from 'src/common/pubsub/pubsub-event' @Injectable() export class UserSchema extends PothosSchema { constructor( @Inject(SchemaBuilderToken) private readonly builder: Builder, private readonly prisma: PrismaService, private readonly mailService: MailService, + private readonly messageSchema: MessageSchema, ) { super() } @@ -366,5 +370,22 @@ export class UserSchema extends PothosSchema { }, }), })) + + // Subscription section + this.builder.subscriptionFields((t) => ({ + userScopedMessage: t.field({ + type: this.messageSchema.message(), + subscribe: async (_, _args, ctx: SchemaContext) => { + if (!ctx.isSubscription) throw new Error('Not allowed') + const { + websocket: { pubSub }, + } = ctx + return pubSub.asyncIterator([ + `${PubSubEvent.NEW_MESSAGE}.${ctx.websocket.me?.id}`, + ]) as unknown as AsyncIterable + }, + resolve: async (payload: Message) => payload, + }), + })) } } diff --git a/src/common/pubsub/pubsub-event.ts b/src/common/pubsub/pubsub-event.ts index e8c021c..a4f9739 100644 --- a/src/common/pubsub/pubsub-event.ts +++ b/src/common/pubsub/pubsub-event.ts @@ -1,5 +1,6 @@ export enum PubSubEvent { SERVICE_CREATED = 'SERVICE_CREATED', MESSAGE_SENT = 'MESSAGE_SENT', + NEW_MESSAGE = 'NEW_MESSAGE', NOTIFICATION = 'NOTIFICATION', }