Skip to content

Commit

Permalink
feat: persist lobby chat messages
Browse files Browse the repository at this point in the history
closes #913

Co-authored-by: Scott Foster <[email protected]>
  • Loading branch information
alee and sgfost committed Nov 8, 2023
1 parent 511d915 commit 2da7b01
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 5 deletions.
2 changes: 1 addition & 1 deletion client/src/components/lobby/LobbyChat.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
:key="msg.username + msg.dateCreated"
class="mt-2 backdrop rounded p-1"
>
<p class="mb-0">
<p class="mb-0 text-break">
<b class="text-light">{{ msg.username }}: </b>
<span class="text-secondary">{{ msg.message }}</span>
</p>
Expand Down
27 changes: 27 additions & 0 deletions server/src/entity/LobbyChatMessage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from "typeorm";
import { GameType } from "@port-of-mars/shared/types"
import { User } from "./User";

@Entity()
export class LobbyChatMessage {
@PrimaryGeneratedColumn()
id!: number;

@Column()
dateCreated!: Date;

@ManyToOne(type => User)
user!: User;

@Column()
userId!: number;

@Column()
message!: string;

@Column()
roomId!: string;

@Column()
lobbyType!: GameType;
}
16 changes: 16 additions & 0 deletions server/src/migration/1699482607231-AddLobbyChatMessage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {MigrationInterface, QueryRunner} from "typeorm";

export class AddLobbyChatMessage1699482607231 implements MigrationInterface {
name = 'AddLobbyChatMessage1699482607231'

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`CREATE TABLE "lobby_chat_message" ("id" SERIAL NOT NULL, "dateCreated" TIMESTAMP NOT NULL, "userId" integer NOT NULL, "message" character varying NOT NULL, "roomId" character varying NOT NULL, "lobbyType" character varying NOT NULL, CONSTRAINT "PK_4640a139c74b0d188cc5efdda33" PRIMARY KEY ("id"))`);
await queryRunner.query(`ALTER TABLE "lobby_chat_message" ADD CONSTRAINT "FK_96a0bc5d48c597dbd5ea6400feb" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "lobby_chat_message" DROP CONSTRAINT "FK_96a0bc5d48c597dbd5ea6400feb"`);
await queryRunner.query(`DROP TABLE "lobby_chat_message"`);
}

}
8 changes: 7 additions & 1 deletion server/src/rooms/lobby/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ export abstract class LobbyRoom<RoomStateType extends LobbyRoomState> extends Ro

onDispose() {
logger.trace(`Disposing of ${this.roomName} ${this.roomId}, no connected clients`);
logger.debug("Saving all lobby chat messages");
const chatMessages = [...this.state.chat]
logger.debug("lobby chat messages %s", chatMessages);
if (chatMessages) {
getServices().tournament.saveLobbyChatMessages(this.roomId, "tournament", chatMessages);
}
}

async getMaxConnections() {
Expand Down Expand Up @@ -152,7 +158,7 @@ export abstract class LobbyRoom<RoomStateType extends LobbyRoomState> extends Ro
logger.trace(`client ${client.auth.username} attempted to send a chat message while muted`);
return;
}
this.state.addChatMessage(client.auth.username, message.value);
this.state.addChatMessage(client.auth, message.value);
});
this.onMessage("accept-invitation", (client: Client, message: AcceptInvitation) => {
this.onAcceptInvitation(client, message);
Expand Down
8 changes: 6 additions & 2 deletions server/src/rooms/lobby/common/state.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Schema, ArraySchema, type } from "@colyseus/schema";
import { Client } from "colyseus";
import { LobbyChatMessageData } from "@port-of-mars/shared/types";
import { User } from "@port-of-mars/server/entity";

/**
* Connected client with additional metadata
Expand Down Expand Up @@ -30,11 +31,13 @@ export class LobbyClient extends Schema {
export class LobbyChatMessage extends Schema implements LobbyChatMessageData {
constructor(msg: LobbyChatMessageData) {
super();
this.userId = msg.userId;
this.username = msg.username;
this.message = msg.message;
this.dateCreated = msg.dateCreated;
}

@type("number") userId: number;
@type("string") username: string;
@type("string") message: string;
@type("number") dateCreated: number;
Expand Down Expand Up @@ -90,9 +93,10 @@ export abstract class LobbyRoomState extends Schema {
}
}

addChatMessage(username: string, message: string) {
addChatMessage(user: User, message: string) {
const data = {
username,
userId: user.id,
username: user.username,
message,
dateCreated: new Date().getTime(),
};
Expand Down
21 changes: 20 additions & 1 deletion server/src/services/tournament.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { MoreThanOrEqual, Not, SelectQueryBuilder } from "typeorm";
import {
User,
Player,
Expand All @@ -7,12 +8,13 @@ import {
Treatment,
Game,
} from "@port-of-mars/server/entity";
import { MoreThanOrEqual, Not, SelectQueryBuilder } from "typeorm";
import { getServices } from "@port-of-mars/server/services";
import { BaseService } from "@port-of-mars/server/services/db";
import { LobbyChatMessage } from "@port-of-mars/server/entity/LobbyChatMessage";
import { TournamentRoundDate } from "@port-of-mars/server/entity/TournamentRoundDate";
import {
GameType,
LobbyChatMessageData,
MarsEventOverride,
TournamentRoundInviteStatus,
TournamentStatus,
Expand Down Expand Up @@ -418,4 +420,21 @@ export class TournamentService extends BaseService {
const offset = await getServices().settings.tournamentLobbyOpenAfterOffset();
return offset * 60 * 1000;
}

/**
* FIXME: might move this into a separate service at some point
* @param roomId
* @param messages
*/
async saveLobbyChatMessages(roomId: string, roomType: GameType, messages: Array<LobbyChatMessageData>) {
const repository = this.em.getRepository(LobbyChatMessage);
const lobbyChatMessages = messages.map(message => repository.create({
roomId,
lobbyType: roomType,
message: message.message,
dateCreated: new Date(message.dateCreated),
userId: message.userId
}));
await repository.save(lobbyChatMessages);
}
}
1 change: 1 addition & 0 deletions shared/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export type GameType = "freeplay" | "tournament";
export type LobbyType = GameType;

export interface LobbyChatMessageData {
userId: number;
username: string;
message: string;
dateCreated: number;
Expand Down

0 comments on commit 2da7b01

Please sign in to comment.