Skip to content

Commit

Permalink
feat: V2 Release, typescript, discordx, slashCommands
Browse files Browse the repository at this point in the history
  • Loading branch information
bycop committed Oct 20, 2023
1 parent 731b683 commit 77c588a
Show file tree
Hide file tree
Showing 15 changed files with 394 additions and 162 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
BOT_TOKEN=your_bot_token
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# files
.vscode
.env
.env.local
package-lock.json
yarn.lock
config.ts

# folders
build
node_modules
10 changes: 0 additions & 10 deletions config.json

This file was deleted.

91 changes: 0 additions & 91 deletions index.js

This file was deleted.

38 changes: 30 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,34 @@
{
"name": "fivemdiscord",
"version": "1.0.0",
"description": "",
"main": "index.js",
"author": "",
"license": "ISC",
"name": "fivem-discord",
"version": "2.0.0",
"private": true,
"license": "MIT",
"type": "module",
"main": "build/main.js",
"scripts": {
"build": "tsc",
"dev": "ts-node-esm src/main.ts",
"start": "node build/main.js",
"watch": "nodemon --exec ts-node-esm src/main.ts",
"build:start": "npm run build && npm run start"
},
"dependencies": {
"discord.js": "^13.5.0",
"gamedig": "^2.0.24"
"@discordx/importer": "^1.2.3",
"@discordx/pagination": "^3.4.1",
"axios": "^1.5.1",
"discord.js": "^14.13.0",
"discordx": "^11.7.6",
"dotenv": "^16.3.1"
},
"devDependencies": {
"@types/node": "^20.5.9",
"nodemon": "^3.0.1",
"prettier": "^3.0.3",
"ts-node": "^10.9.1",
"typescript": "5.2.2"
},
"engines": {
"node": ">=16.0.0",
"npm": ">=7.0.0"
}
}
109 changes: 56 additions & 53 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,53 +1,56 @@
# Fivem Discord Serverstats

## Introduction

A simple node.js bot to send serverstats, playerlist and playercount of a Fivem Server to a Discord channel.

## Needs

You need to install Node.js and have a discord bot token on this page : https://discord.com/developers/applications

## Installation

Once you download the files and install node.js, make 'npm install' in the project folder. Then, go to the config.json file and add the asked informations
```javascript
{
"prefix" : "!", //Your bot prefix
"discord" : "Discord ID", //Discord server ID where the bot is
"channel" : "Voice Channel ID" //The channel were the playercount can be write
"ipabs" : "Server IP", //The server ip
"port" : "Server port (like 30120)", //The server port
"activity" : "GameActivity", //The message display on "Playing as"
"max" : "100", //Max users of the server
"token" : "" //Your bot token
}
```
Here you can disable the playercount voice channel, just delete the line channel.setName.
```javascript
bot.on('ready', () => {
var interval = setInterval(function () {
let guild = bot.guilds.cache.get(config.discord);
let channel = guild.channels.cache.get(config.channel);
Gamedig.query({
type: 'fivem',
host: config.ipabs, // This needs to be a string
port: config.port // This needs to be a number & is optional, unless you're not using the default port for that gameserver type
}).then((state) => {
bot.user.setActivity(state.raw.clients + "/" + state.maxplayers);
channel.setName(state.raw.clients + " Connected"); // Enable or disable the Channel player count
}).catch((error) => {
console.log(error);
});
}, 1000);
});
```

When you run the bot, the three commands are !serverstats, !playerlist and !playercount.

## Others Bots

Discord-global-chat : https://github.com/bycop/Discord-global-chat <br>
Discord-Image-to-twitter : https://github.com/bycop/Discord-Image-to-twitter <br>
Discord-Serverlist-InviteLinkByID : https://github.com/bycop/Discord-Serverlist-InviteLinkByID <br>
Discord-csgo-Serverstats : https://github.com/bycop/Discord-csgo-Serverstats
# Discord FiveM Serverstats

## Introduction

A Typescript Discord bot to get information about your FiveM server with commands, refreshed embed, ...

## Needs

You need to install Node.js and get a discord bot token on this page : https://discord.com/developers/applications

## Installation

```sh
git clone https://github.com/bycop/Discord-Fivem-Serverstats # Or download it
cd Discord-Fivem-Serverstats
npm install
```
After downloading and installing npm dependencies you'll have to make some configurations:
1. Bot token:
- Rename the `.env.example` file to `.env`
- Replace `your_bot_token` by your token on [Discord Developer Portal](https://discord.com/developers/applications)
2. Configuration file:
- In the `src/utils` folder, rename `config.example.ts` to `config.ts`
- Then fill every needed informations:

```typescript
export const config: IConfig = {
api: "http://lite.gtaliferp.fr:30120", // Your FiveM IP:port server
guildId: "", // Your Discord server ID
refreshEmbed: { // Comment or delete to disable this module (Details below)
channelId: "1164955066961248266", // Channel ID where the embed should be
messageId: "1164955160125132851" // Message ID of the embed
},
refreshChannel: { // Comment or delete to disable this module
channelId: "1164947634268684428", // Channel ID to be renamed/topic changed automatically
type: "both" // "name" for channel rename only, "topic" for channel topic only, "both" for both
},
refreshInterval: 300000 // Do not set this value to low or you can be rate limited by API/Discord
}
```

3. Configure auto-refresh Embed
- Launch the bot with the command `npm run dev`
- Then do the command `/setup` in the desired channel and copy the Message ID of the new message
- Then put it on the config above

With all of this you've 2 commands:
`/players`: To show the full list of connecteds players of your server
`/count`: Show the amount of connecteds players / max players

## Others Bots

Discord-global-chat : https://github.com/bycop/Discord-global-chat <br>
Discord-Image-to-twitter : https://github.com/bycop/Discord-Image-to-twitter <br>
Discord-Serverlist-InviteLinkByID : https://github.com/bycop/Discord-Serverlist-InviteLinkByID <br>
Discord-csgo-Serverstats : https://github.com/bycop/Discord-csgo-Serverstats
22 changes: 22 additions & 0 deletions src/commands/count.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type { CommandInteraction } from "discord.js";
import { Discord, Slash } from 'discordx';

import { makeRequest } from '../utils/functions.js';
import { IDynamic, IEndpoints } from '../utils/types.js';

@Discord()
export class CountCommand {
@Slash({ description: "Returns the number of players on the server", defaultMemberPermissions: ["Administrator"] })
async count(interaction: CommandInteraction): Promise<void> {
await interaction.deferReply({ fetchReply: true });

const dynamic = await makeRequest(IEndpoints.dynamic) as IDynamic;

if ("error" in dynamic) {
interaction.editReply(`Error: ${dynamic.error}`);
}
else {
interaction.editReply(`There are currently **${dynamic.clients}** / **${dynamic.sv_maxclients}** players on the server`);
}
}
}
43 changes: 43 additions & 0 deletions src/commands/players.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { type CommandInteraction, EmbedBuilder } from 'discord.js';
import { Discord, Slash } from 'discordx';

import { Pagination, PaginationType } from '@discordx/pagination';

import { makeRequest } from '../utils/functions.js';
import { IEndpoints, IPlayer, IPlayers } from '../utils/types.js';

@Discord()
export class PlayersCommand {
@Slash({ description: "Returns the list of players on the server", defaultMemberPermissions: ["Administrator"] })
async players(interaction: CommandInteraction): Promise<any> {
await interaction.deferReply({ fetchReply: true });

const players = await makeRequest(IEndpoints.players) as IPlayers;

if ("error" in players) return interaction.editReply(`Error: ${players.error}`);

let embeds = [];

for (let i = 0; i < players.length / 25; i++)
embeds.push({
embeds: [new EmbedBuilder()
.setTitle(`Players list (${players.length})`)
.setDescription(players.slice(i * 25, 25 * (i + 1)).map((player: IPlayer, index: number) => {
return `${index + (i * 25) + 1}. ${player.name} - ${player.id} - ${player.ping}ms`
}).join("\n").replaceAll("`", "'"))
.setColor("#088408")
.setTimestamp()]
});

const pagination = new Pagination(interaction, embeds, {
time: 120000,
type: PaginationType.Button,
async onTimeout(page, message) {
await interaction.editReply({ embeds: message.embeds, content: message.content ? message.content : undefined, components: [] })
},
showStartEnd: false
});

await pagination.send();
}
}
12 changes: 12 additions & 0 deletions src/commands/setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { CommandInteraction } from "discord.js";
import { Discord, Slash } from 'discordx';

@Discord()
export class SetupCommand {
@Slash({ description: "Send an empty message to be configured for auto embed refresh", defaultMemberPermissions: ["Administrator"] })
setup(interaction: CommandInteraction): void {
interaction.reply({ content: "Setting up...", ephemeral: true });

interaction.channel!.send("This message will be updated every 5 minutes with the latest server information when the bot is configured.\nYou can now copy the message ID and paste it in the config file with the channel ID.")
}
}
27 changes: 27 additions & 0 deletions src/events/ready.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import type { Client } from "discordx";
import { Discord, On } from 'discordx';

import { bot } from '../main.js';
import config from '../utils/config.js';
import { refreshChannel, refreshEmbed } from '../utils/functions.js';

@Discord()
export class ReadyEvent {
@On()
async ready([client]: [Client]): Promise<void> {
await bot.initApplicationCommands();
console.log("Bot started");

setInterval(async () => {
const guild = await client.guilds.fetch(config.guildId);
if (guild) {
if (config.refreshChannel?.channelId) {
refreshChannel(guild, config.refreshChannel.channelId);
}
if (config.refreshEmbed?.channelId && config.refreshEmbed?.messageId) {
refreshEmbed(guild, config.refreshEmbed.channelId, config.refreshEmbed.messageId);
}
}
}, config.refreshInterval);
}
}
Loading

0 comments on commit 77c588a

Please sign in to comment.