Skip to content

Commit

Permalink
notify module
Browse files Browse the repository at this point in the history
  • Loading branch information
Bilaboz committed Nov 10, 2023
1 parent c987b1f commit 6a3e921
Show file tree
Hide file tree
Showing 10 changed files with 88 additions and 30 deletions.
13 changes: 13 additions & 0 deletions api/prisma/migrations/20231110173333_user_status/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
Warnings:
- You are about to drop the column `isConnected` on the `User` table. All the data in the column will be lost.
- Added the required column `status` to the `User` table without a default value. This is not possible if the table is not empty.
*/
-- CreateEnum
CREATE TYPE "UserStatus" AS ENUM ('OFFLINE', 'ONLINE', 'INGAME');

-- AlterTable
ALTER TABLE "User" DROP COLUMN "isConnected",
ADD COLUMN "status" "UserStatus" NOT NULL;
8 changes: 7 additions & 1 deletion api/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,18 @@ enum ChannelRole {
OWNER
}

enum UserStatus {
OFFLINE
ONLINE
INGAME
}

model User {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
login String @unique
email String @unique
isConnected Boolean
status UserStatus
imageUrl String?
displayName String @unique
firstName String
Expand Down
6 changes: 4 additions & 2 deletions api/src/modules/auth/auth.dto.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { IsEmail, IsNotEmpty } from 'class-validator';
import { UserStatus } from '@prisma/client';
import { IsEmail, IsEnum, IsNotEmpty } from 'class-validator';

export class JwtPayload {
login: string;
Expand All @@ -21,7 +22,8 @@ export class CreateUserDto {
@IsNotEmpty()
lastName: string;

isConnected: boolean;
@IsEnum(UserStatus)
status: UserStatus;

bannerUrl: string;

Expand Down
3 changes: 2 additions & 1 deletion api/src/modules/auth/auth.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Injectable, Logger, NotFoundException } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { UserStatus } from '@prisma/client';
import axios from 'axios';

import { UserService } from '../user';
Expand Down Expand Up @@ -60,7 +61,7 @@ export class AuthService {
firstName: profile.first_name,
lastName: profile.last_name,
description: 'No description atm.',
isConnected: true,
status: UserStatus.OFFLINE,
bannerUrl: 'Good banner to place here',
};
} catch (error) {
Expand Down
1 change: 1 addition & 0 deletions api/src/modules/notify/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './notify.module';
export * from './notify.service';
28 changes: 13 additions & 15 deletions api/src/modules/notify/notify.gateway.ts
Original file line number Diff line number Diff line change
@@ -1,52 +1,50 @@
import { Logger, UseFilters, UseGuards, UsePipes, ValidationPipe } from '@nestjs/common';
import { Logger, UseFilters, UseGuards } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import {
OnGatewayConnection,
OnGatewayDisconnect,
OnGatewayInit,
WebSocketGateway,
WebSocketServer,
} from '@nestjs/websockets';
import { Server, Socket } from 'socket.io';

import { HttpExceptionTransformationFilter } from '@/utils/ws-http-exception.filter';

import { WSAuthMiddleware } from '../auth/ws/ws.middleware';
import { WsJwtGuard } from '../auth/ws/ws-jwt.guard';
import { FriendService, UserService } from '../user';
import { UserService } from '../user';
import { NotifyService } from './notify.service';

@UseGuards(WsJwtGuard)
@UsePipes(new ValidationPipe())
@WebSocketGateway({ namespace: 'notify' })
@UseFilters(HttpExceptionTransformationFilter)
export class NotifyGateway implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect {
@WebSocketServer()
private io: Server;
private logger: Logger = new Logger(NotifyGateway.name);
private socketsID: Map<string, string> = new Map<string, string>();
private sockets: Map<string, Socket> = new Map<string, Socket>();

constructor(
private jwtService: JwtService,
private userService: UserService,
private friendService: FriendService,
private notifyService: NotifyService,
) {}

afterInit(server: Server) {
const authMiddleware = WSAuthMiddleware(this.jwtService, this.userService);
server.use(authMiddleware);

this.notifyService.sockets = this.sockets;
}

async handleConnection(socket: Socket) {
this.logger.log('Client connected: ' + socket.id);
this.socketsID.set(socket.data.user.login, socket.id);
this.sockets.set(socket.data.user.login, socket);

const friends = await this.friendService.getFriendList(socket.data.user);
for (const friend of friends) {
const socketID = this.socketsID.get(friend.login);
}
await this.notifyService.online(socket.data.user);
}

handleDisconnect(socket: Socket) {
this.socketsID.delete(socket.data.user.login);
async handleDisconnect(socket: Socket) {
await this.notifyService.offline(socket.data.user);

this.sockets.delete(socket.data.user.login);
}
}
8 changes: 5 additions & 3 deletions api/src/modules/notify/notify.module.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { Module } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';

import { FriendService, UserService } from '../user';
import { UserModule } from '../user';
import { NotifyGateway } from './notify.gateway';
import { NotifyService } from './notify.service';

@Module({
controllers: [],
providers: [NotifyService, JwtService, UserService, FriendService],
providers: [NotifyGateway, NotifyService],
imports: [UserModule],
exports: [NotifyService],
})
export class NotifyModule {}
37 changes: 36 additions & 1 deletion api/src/modules/notify/notify.service.ts
Original file line number Diff line number Diff line change
@@ -1 +1,36 @@
export class NotifyService {}
import { Injectable } from '@nestjs/common';
import { User, UserStatus } from '@prisma/client';
import { Socket } from 'socket.io';

import { FriendService } from '../user';

@Injectable()
export class NotifyService {
public sockets: Map<string, Socket>;

constructor(private friendService: FriendService) {}

async emitToFriends(user: User, status: UserStatus) {
const friends = await this.friendService.getFriendList(user, true);

for (const friend of friends) {
const socket = this.sockets.get(friend.login);

if (socket) {
socket.emit('notify', { user: user, status: status });
}
}
}

async online(user: User) {
await this.emitToFriends(user, UserStatus.ONLINE);
}

async offline(user: User) {
await this.emitToFriends(user, UserStatus.OFFLINE);
}

async inGame(user: User) {
await this.emitToFriends(user, UserStatus.INGAME);
}
}
6 changes: 3 additions & 3 deletions api/test/game/game.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Test } from '@nestjs/testing';
import { Game, PrismaClient, User } from '@prisma/client';
import { Game, PrismaClient, User, UserStatus } from '@prisma/client';
import { DeepMockProxy, mockDeep } from 'jest-mock-extended';

import { GameService } from '../../src/modules/game';
Expand Down Expand Up @@ -40,7 +40,7 @@ describe('Gameservice', () => {
displayName: 'testLoginOne',
firstName: 'testFirstNameOne',
lastName: 'testLastNameOne',
isConnected: true,
status: UserStatus.ONLINE,
bannerUrl: 'bannerUrlOne',
description: 'descriptionOne',
createdAt: new Date(),
Expand All @@ -54,7 +54,7 @@ describe('Gameservice', () => {
displayName: 'testLoginTwo',
firstName: 'testFirstNameTwo',
lastName: 'testLastNameTwo',
isConnected: true,
status: UserStatus.ONLINE,
bannerUrl: 'bannerUrlTwo',
description: 'descriptionTwo',
createdAt: new Date(),
Expand Down
8 changes: 4 additions & 4 deletions api/test/user/user.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Test } from '@nestjs/testing';
import { PrismaClient } from '@prisma/client';
import { PrismaClient, UserStatus } from '@prisma/client';
import { DeepMockProxy, mockDeep } from 'jest-mock-extended';

import { CreateUserDto } from '@/modules/auth';
Expand Down Expand Up @@ -45,7 +45,7 @@ describe('UserService', () => {
displayName: 'testLogin',
firstName: 'testFirstName',
lastName: 'testLastName',
isConnected: true,
status: UserStatus.ONLINE,
bannerUrl: 'bannerUrl',
description: 'description',
createdAt: new Date(),
Expand All @@ -58,7 +58,7 @@ describe('UserService', () => {
displayName: 'testLogin',
firstName: 'testFirstName',
lastName: 'testLastName',
isConnected: true,
status: UserStatus.ONLINE,
bannerUrl: 'bannerUrl',
description: 'description',
};
Expand Down Expand Up @@ -101,7 +101,7 @@ describe('UserService', () => {
displayName: 'newDisplayName',
firstName: 'testFirstName',
lastName: 'testLastName',
isConnected: true,
status: UserStatus.ONLINE,
bannerUrl: 'new bannerUrl',
description: 'description',
createdAt: new Date(),
Expand Down

0 comments on commit 6a3e921

Please sign in to comment.