Skip to content

Commit a02bfdb

Browse files
authored
feat(get-my-servers): implement new command to retrieve your server data (#226)
1 parent c9640ba commit a02bfdb

12 files changed

Lines changed: 529 additions & 13 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@
6262
| Command | Description |
6363
|--------|-------------|
6464
| `/create-server <region>` | Launches a server in the selected region (you'll be prompted to select a variant) |
65+
| `/get-my-servers` | Retrieves all your active server details (IPs, passwords, etc.) in case you lost the original message |
66+
| `/status` | Shows the current status of all servers across all regions (running, pending, terminating counts) |
6567
| `/terminate-servers` | Terminates all servers created by the user |
6668
| `/set-user-data <steamId>` | Sets the SteamID of the user, assigning them as the Sourcemod admin for all servers the user creates |
6769

packages/core/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export * from './src/usecase/DeleteServer';
4141
export * from './src/usecase/DeleteServerForUser';
4242
export * from './src/usecase/GenerateMonthlyUsageReport';
4343
export * from './src/usecase/GetServerStatus';
44+
export * from './src/usecase/GetUserServers';
4445
export * from './src/usecase/HandleOrderPaid';
4546
export * from './src/usecase/SetUserData';
4647
export * from './src/usecase/TerminateEmptyServers';
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import { describe, expect, it } from "vitest";
2+
import { mock } from "vitest-mock-extended";
3+
import { when } from "vitest-when";
4+
import { Server, Region } from "../domain";
5+
import { ServerRepository } from "../repository/ServerRepository";
6+
import { GetUserServers } from "./GetUserServers";
7+
import Chance from "chance";
8+
9+
const chance = new Chance();
10+
11+
describe("GetUserServers", () => {
12+
const makeSut = () => {
13+
const serverRepository = mock<ServerRepository>();
14+
const sut = new GetUserServers({ serverRepository });
15+
return { sut, serverRepository };
16+
};
17+
18+
it("should return all servers for a given user", async () => {
19+
// Given
20+
const { sut, serverRepository } = makeSut();
21+
const userId = chance.guid();
22+
const servers: Server[] = [
23+
{
24+
serverId: chance.guid(),
25+
region: Region.SA_SAOPAULO_1,
26+
variant: "standard-competitive",
27+
hostIp: chance.ip(),
28+
hostPort: 27015,
29+
tvIp: chance.ip(),
30+
tvPort: 27020,
31+
rconPassword: chance.word(),
32+
rconAddress: `${chance.ip()}:27015`,
33+
hostPassword: chance.word(),
34+
tvPassword: chance.word(),
35+
status: "ready",
36+
createdBy: userId
37+
},
38+
{
39+
serverId: chance.guid(),
40+
region: Region.US_CHICAGO_1,
41+
variant: "standard-competitive",
42+
hostIp: chance.ip(),
43+
hostPort: 27015,
44+
tvIp: chance.ip(),
45+
tvPort: 27020,
46+
rconPassword: chance.word(),
47+
rconAddress: `${chance.ip()}:27015`,
48+
hostPassword: chance.word(),
49+
tvPassword: chance.word(),
50+
status: "pending",
51+
createdBy: userId
52+
}
53+
];
54+
55+
when(serverRepository.getAllServersByUserId)
56+
.calledWith(userId)
57+
.thenResolve(servers);
58+
59+
// When
60+
const result = await sut.execute({ userId });
61+
62+
// Then
63+
expect(result).toEqual(servers);
64+
expect(serverRepository.getAllServersByUserId).toHaveBeenCalledWith(userId);
65+
});
66+
67+
it("should return an empty array when user has no servers", async () => {
68+
// Given
69+
const { sut, serverRepository } = makeSut();
70+
const userId = chance.guid();
71+
72+
when(serverRepository.getAllServersByUserId)
73+
.calledWith(userId)
74+
.thenResolve([]);
75+
76+
// When
77+
const result = await sut.execute({ userId });
78+
79+
// Then
80+
expect(result).toEqual([]);
81+
expect(serverRepository.getAllServersByUserId).toHaveBeenCalledWith(userId);
82+
});
83+
84+
});
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { Server } from "../domain";
2+
import { ServerRepository } from "../repository/ServerRepository";
3+
4+
type GetUserServersParams = {
5+
userId: string;
6+
}
7+
8+
export class GetUserServers {
9+
constructor(private readonly dependencies: {
10+
serverRepository: ServerRepository;
11+
}) { }
12+
13+
async execute(params: GetUserServersParams): Promise<Server[]> {
14+
const { serverRepository } = this.dependencies;
15+
const { userId } = params;
16+
17+
const servers = await serverRepository.getAllServersByUserId(userId);
18+
return servers;
19+
}
20+
}

packages/entrypoints/src/commands/CreateServer/handler.ts

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { commandErrorHandler } from "../commandErrorHandler";
1717
import { defaultGracefulShutdownManager } from "@tf2qs/providers";
1818
import { BackgroundTaskQueue } from "@tf2qs/core";
1919
import { DeleteServerForUserTaskData } from "@tf2qs/providers";
20+
import { formatServerMessage } from "../formatServerMessage";
2021

2122
export function createServerCommandHandlerFactory(dependencies: {
2223
createServerForUser: CreateServerForUser,
@@ -111,19 +112,7 @@ export function createServerCommandHandlerFactory(dependencies: {
111112
return;
112113
}
113114
await buttonInteraction.followUp({
114-
content: `🎉 **Server Created Successfully!** 🎉\n\n` +
115-
`🆔 **Server ID:** \`${deployedServer.serverId}\`\n` +
116-
`🌍 **Region:** \`${getRegionDisplayName(deployedServer.region)}\`\n` +
117-
`🎮 **Variant:** \`${deployedServer.variant}\`\n\n` +
118-
`**CONNECT Addresses:**\n` +
119-
`- **SDR Connect:**\n` +
120-
`\`\`\`\nconnect ${deployedServer.hostIp}:${deployedServer.hostPort};${deployedServer.hostPassword ? `password ${deployedServer.hostPassword}` : ''}\n\`\`\`\n` +
121-
`- **Direct Connect:**\n` +
122-
`\`\`\`\nconnect ${deployedServer.rconAddress}:27015;${deployedServer.hostPassword ? `password ${deployedServer.hostPassword}` : ''}\n\`\`\`\n` +
123-
`- **TV Connect:**\n` +
124-
`\`\`\`\nconnect ${deployedServer.tvIp}:${deployedServer.tvPort};${deployedServer.tvPassword ? `password ${deployedServer.tvPassword}` : ''}\n\`\`\`\n` +
125-
`⚠️ **Warning:** If you are connecting from the SDR IP, use the following RCON commands in the console:\n` +
126-
`\`\`\`\nrcon_address ${deployedServer.rconAddress}\nrcon_password ${deployedServer.rconPassword}\n\`\`\`\n`,
115+
content: `🎉 **Server Created Successfully!** 🎉\n\n${formatServerMessage(deployedServer)}`,
127116
flags: MessageFlags.Ephemeral
128117
});
129118
} catch (error: Error | any) {
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { SlashCommandBuilder } from "discord.js";
2+
3+
export const getMyServersCommandDefinition = new SlashCommandBuilder()
4+
.setName('get-my-servers')
5+
.setDescription('Retrieve all your active server details (IPs, passwords, etc.)');

0 commit comments

Comments
 (0)