Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion src/fivem/fivem.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ import { ApiOkResponse, ApiOperation, ApiTags } from '@nestjs/swagger';
import { Cache } from 'cache-manager';
import ServerTrackedDto from 'src/dto/serverTrackedDto';
import ServerCfxDto from 'src/dto/serverCfxDto';
import { fivemCfxResponse, fivemPlayersResponse, fivemResponse } from './fivem.schema';
import { fivemCfxResponse, fivemInfoResponse, fivemPlayersResponse, fivemResponse } from './fivem.schema';
import { CACHE_MANAGER } from '@nestjs/cache-manager';
import { CacheKeys } from 'src/utils/enums';

/*
CODE CacheKey
- FM : FiveM Track server by Address
- FMI : FiveM Track server Info
- FMCFX : FiveM Track server by CFX Code
- FMP : FiveM Track Players
*/
Expand Down Expand Up @@ -89,4 +90,26 @@ export class FivemController {
this.cacheManager.set(`${CacheKeys.FiveMPlayers}:${address.address}`, result, 5 * 60 * 1000);
return result;
}

@Get('/info/:address')
@ApiOperation({
summary: "Track a FiveM Server's info",
description: "Return a JSON response with information about the server",
})
@ApiOkResponse({
description: 'Server information',
schema: fivemInfoResponse
})
async getServerInfo(@Param() address: ServerTrackedDto): Promise<any> {
const cache: any = await this.cacheManager.get(`${CacheKeys.FiveMInfo}:${address.address}`);
let result: any;

if (cache)
return cache;
result = await this.service.trackInfo(address);
result["cacheTime"] = Math.floor(Date.now() / 1000);
result["cacheExpire"] = Math.floor(Date.now() / 1000) + (5 * 60);
this.cacheManager.set(`${CacheKeys.FiveMInfo}:${address.address}`, result, 5 * 60 * 1000);
return result;
}
}
62 changes: 62 additions & 0 deletions src/fivem/fivem.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -285,8 +285,70 @@ const fivemCfxResponse: SchemaObject & Partial<ReferenceObject> = {
}
}

const fivemInfoResponse: SchemaObject & Partial<ReferenceObject> = {
type: 'object',
properties: {
address: { type: 'string', description: "Server's address" },
online: { type: 'boolean', description: "Server's status. If the bool is true, the server is online" },
cacheTime: { type: 'number', description: "UNIX timestamp when the response was cached" },
cacheExpire: { type: 'number', description: "UNIX timestamp when the response will be remove from cache. Around 5 minutes." },
enhancedHostSupport: { type: 'boolean', description: "Enhanced host support", nullable: true },
icon: { type: 'string', description: "Server's icon in base64 format", nullable: true },
resources: {
type: 'array',
description: "List of resources used by the server",
nullable: true,
items: { type: 'string' }
},
server: { type: 'string', nullable: true, description: "Server's software" },
version: { type: 'number', nullable: true, description: "Server's version" },
vars: {
type: 'object',
description: "Server's variables",
nullable: true,
properties: {
sv_disableClientReplays: { type: 'boolean', nullable: true },
sv_enforceGameBuild: { type: 'number', nullable: true },
sv_enhancedHostSupport: { type: 'boolean', nullable: true },
sv_lan: { type: 'boolean', nullable: true },
sv_licenseKeyToken: { type: 'string', nullable: true },
sv_maxClients: { type: 'number', nullable: true },
sv_poolSizesIncrease: { type: 'string', nullable: true },
sv_projectDesc: { type: 'string', nullable: true },
sv_projectName: { type: 'string', nullable: true },
sv_pureLevel: { type: 'number', nullable: true },
sv_replaceExeToSwitchBuilds: { type: 'boolean', nullable: true },
sv_scriptHookAllowed: { type: 'boolean', nullable: true },
}
}
},
example: {
enhancedHostSupport: true,
icon: "data:image/png;base64,...",
requestSteamTicket: "off",
resources: ["hardcap", "_cfx_internal", "mapmanager"],
server: "FXServer-master SERVER v1.0.0.6228 win32",
version: 123,
vars: {
sv_disableClientReplays: true,
sv_enforceGameBuild: 2802,
sv_enhancedHostSupport: true,
sv_lan: false,
sv_licenseKeyToken: "abcdef123456",
sv_maxClients: 32,
sv_poolSizesIncrease: "2048",
sv_projectDesc: "My FiveM server",
sv_projectName: "My FiveM server description",
sv_pureLevel: 1,
sv_replaceExeToSwitchBuilds: false,
sv_scriptHookAllowed: false
}
}
};

export {
fivemResponse,
fivemInfoResponse,
fivemPlayersResponse,
fivemCfxResponse
};
26 changes: 26 additions & 0 deletions src/fivem/fivem.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,32 @@ export class FivemService {
}
}

async trackInfo(serverTracked: ServerTrackedDto): Promise<any> {
try {
const response: Response = await fetch(
`http://${serverTracked.address}/info.json`,
{
method: 'GET',
signal: AbortSignal.timeout(2000),
}
)
const data = await response.json();
return {
address: serverTracked.address,
online: true,
...data,
};
} catch (err: any) {
Logger.warn(
`[FiveM server | ${serverTracked.address}] ${err.name}: ${err.message}`,
);
return {
address: serverTracked.address,
online: false,
};
}
}

async trackServerByCfx(cfx: ServerCfxDto): Promise<any> {
try {
let response: Response = await fetch(
Expand Down
1 change: 1 addition & 0 deletions src/utils/enums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ enum CacheKeys {
FiveM = "FM",
FiveMCfxCode = "FMCFX",
FiveMPlayers = "FMP",
FiveMInfo = "FMI",
Minecraft = "MC",
MinecraftQuery = "MCQ",
MinecraftBedrock = "MCB",
Expand Down