Skip to content

Commit

Permalink
Merge pull request #7 from bl3rune/http-server
Browse files Browse the repository at this point in the history
Added options for HTTP server, UDP listen port, default UP DOWN messages
  • Loading branch information
bl3rune authored Mar 3, 2024
2 parents 918cee3 + eb9c375 commit 1383a2e
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 45 deletions.
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ DISCORD_TOKEN=
DISCORD_CHANNEL=000000000000
UP.przomboid=':zombie: The Project Zomboid server is available!'
UP.minecraft=':pick: The Minecraft server is available!'
UP='The sever is available'
DOWN.minecraft=':pick: The Minecraft server is no longer available!'
UP='The sever is unavailable'

# Mapping settings
SEPERATOR=' +++++ '
Expand Down
31 changes: 18 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ This format holds 3 key pieces of information:
- The hostname / IP address of the game server you want to query.
- (Optional) The query port configured for the game server.

This information is formatted in the following structure with the port being optional : `game:host:port`
This information is formatted in the following structure with the port being optional : `game:host:port` or `game:host`
Here are some examples below:
- Omitting port number `przomboid:mysite.com`
- With port number `minecraft:mysite.com:25565`
Expand All @@ -39,15 +39,20 @@ When running as a docker container provide the following as Docker environment v
When running as a nodejs app you can create an `.env` file in the root directory of the project and set the options there (see the `.env.example` file for an example).
You need to set the following configuration options.

| Required | Configuration option | Description | Value |
| -------- | ---------------------- | ----------- | ------ |
| TRUE | `GAME_URLS` | Comma seperated list of GameUrl format entries [see GameUrl format section](#gameurl-format) | `string` |
| TRUE | `DISCORD_TOKEN` | The bot token of your discord app from https://discord.com/developers/applications -> (Select your application) -> Bot -> Token | `string` |
| FALSE | `DISCORD_CHANNEL` | The channel id of your discord chat to send server availability to | `string` |
| FALSE | `UP.####` | Message to be sent on server available for game type #### (DISCORD_CHANNEL must be provided) | `string` |
| FALSE | `DOWN.####` | Message to be sent on server unavailable for game type #### (DISCORD_CHANNEL must be provided) | `string` |
| FALSE | `IDLE_STATUS` | Override idle status messaging for the bot when no servers are available | `string` |
| FALSE | `SEPERATOR` | Override the seperator text that appears between multiple activities | `string` |
| FALSE | `NAME_OVERRIDE.####` | Override the activity name for game type #### with : variable string value | `string` |
| FALSE | `NAME_FIELD.####` | Override the activity name for game type #### with : field on the response object (response[NAME_FIELD]) | `string` |
| FALSE | `RAW_NAME_FIELD.####` | Override the activity name for game type #### with : field in the raw section of the response (response.raw[RAW_NAME_FIELD]) | `string` |
| Required | Configuration option | Default | Description | Value |
| -------- | ---------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------- | -------- |
| TRUE | `GAME_URLS` | | Comma seperated list of GameUrl format entries [see GameUrl format section](#gameurl-format) | `string` |
| TRUE | `DISCORD_TOKEN` | | The bot token of your discord app from https://discord.com/developers/applications -> (Select your application) -> Bot -> Token | `string` |
| FALSE | `DISCORD_CHANNEL` | | The channel id of your discord chat to send server availability to | `string` |
| FALSE | `UP.####` | | Message to be sent on server available for game type `####` (`DISCORD_CHANNEL` must be provided) | `string` |
| FALSE | `DOWN.####` | | Message to be sent on server unavailable for game type `####` (`DISCORD_CHANNEL` must be provided) | `string` |
| FALSE | `UP` | | Message to be sent on server available for any game when `UP.####` is not available (`DISCORD_CHANNEL` must be provided) | `string` |
| FALSE | `DOWN` | | Message to be sent on server unavailable for any game when `DOWN.####` is not available (`DISCORD_CHANNEL` must be provided) | `string` |
| FALSE | `IDLE_STATUS` | `No servers running`| Override idle status messaging for the bot when no servers are available | `string` |
| FALSE | `SEPERATOR` | ` ///// ` | Override the seperator text that appears between multiple activities | `string` |
| FALSE | `NAME_OVERRIDE.####` | | Override the activity name for game type `####` with : variable string value | `string` |
| FALSE | `NAME_FIELD.####` | | Override the activity name for game type `####` with : field on the response object (response[NAME_FIELD]) | `string` |
| FALSE | `RAW_NAME_FIELD.####` | | Override the activity name for game type `####` with : field in the raw section of the response (response.raw[RAW_NAME_FIELD]) | `string` |
| FALSE | `UDP_PORT` | | Use a fixed UDP port see https://www.npmjs.com/package/gamedig/v/4.3.1#specifying-a-listen-udp-port-override | `string` |
| FALSE | `HTTP_ENABLED` | FALSE | Enable the HTTP server that handles direct requests in the format : `/server/port/protocol` or `/server/port` | `boolean`|
| FALSE | `HTTP_PORT` | 80 | HTTP port to host server on and handle requests in the format : `/server/port/protocol` or `/server/port` | `string` |
40 changes: 20 additions & 20 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"author": "ben.lang",
"license": "MIT",
"dependencies": {
"discord.js": "^14.14.1",
"discord.js": "^14.12.1",
"dotenv": "^16.3.1",
"gamedig": "^4.2.0",
"rxjs": "^7.8.1"
Expand Down
6 changes: 3 additions & 3 deletions src/app.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {GamedigQueryProvider} from './services/gamedig-query-provider';
import {DiscordPublisher} from './services/discord-publisher';
import {Subscription} from 'rxjs';
import { GamedigQueryProvider } from './services/gamedig-query-provider';
import { DiscordPublisher } from './services/discord-publisher';
import { Subscription } from 'rxjs';

export class App {
private provider: GamedigQueryProvider;
Expand Down
33 changes: 33 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { config } from 'dotenv';
import { App } from './app';
import { Type as GameType } from 'gamedig';
import Gamedig = require("gamedig");
const http = require("http");

config();

Expand All @@ -13,6 +16,36 @@ app.isReady().then(async () => {
process.exit(1);
});

const gamedig = new Gamedig({ listenUdpPort: process.env.UDP_PORT ? parseInt(process.env.UDP_PORT) : undefined});
const httpPort = process.env.HTTP_PORT ? parseInt(process.env.HTTP_PORT) : 80;

if (!process.env.HTTP_ENABLED) {
http.createServer(async (req: any, res: any) => {
let urlPath = req.url;
if (urlPath.charAt(0) == "/") urlPath = urlPath.substr(1);
const rawGameUrl = urlPath.split('/');
const gameString = rawGameUrl[0];
const host = rawGameUrl[1];
const port = rawGameUrl[2] ? parseInt(rawGameUrl[2]) : undefined;

if (urlPath === "/" || urlPath === "") {
res.end('Use gamedig queries like /server/port/protocol or /server/port (assumes default game port)');
} else {
try {
const data = await gamedig.query({
type: gameString as GameType,
host: host,
port: port,
}).catch(e => "Failed to connect to game server");
res.write(JSON.stringify(data))
} catch(e) {
res.write(e + " : see list of supported games (https://www.npmjs.com/package/gamedig#user-content-games-list) for the Game Type ID of your game");
}
res.end();
}
}).listen(httpPort, "localhost", () => console.log("Listening for requests at " + httpPort));
}

process.on('SIGINT', () => {
console.log('App is shutting down on user event');
app.shutdown();
Expand Down
6 changes: 3 additions & 3 deletions src/services/discord-publisher.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {ActivityType, Client, GatewayIntentBits, TextBasedChannel} from 'discord.js';
import { ActivityType, Client, GatewayIntentBits, TextBasedChannel } from 'discord.js';
import { Type } from 'gamedig';
import { ServerResponse } from '../models/server-response';

Expand Down Expand Up @@ -101,9 +101,9 @@ private serverUp: Map<Type,boolean>;
const textChat = channel as TextBasedChannel;
let message = '';
if (serverUp) {
message = process.env['UP' + '.' + game] || '';
message = process.env['UP' + '.' + game] || process.env['UP'] || '';
} else {
message = process.env['DOWN' + '.' + game] || '';
message = process.env['DOWN' + '.' + game] || process.env['DOWN'] || '';
}
if (message !== '') {
textChat.send(message);
Expand Down
10 changes: 6 additions & 4 deletions src/services/gamedig-query-provider.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import {PollingProvider} from './polling-provider';
import {query, Type} from 'gamedig';
import { PollingProvider } from './polling-provider';
import { Type } from 'gamedig';
import Gamedig = require("gamedig");
import { GameUrl } from '../models/game-url';
import { ServerResponse } from '../models/server-response';
import { Observable } from 'rxjs';

export class GamedigQueryProvider extends PollingProvider {

private gameUrls: GameUrl[];

private gamedig = new Gamedig({ listenUdpPort: process.env.UDP_PORT ? parseInt(process.env.UDP_PORT) : undefined});

constructor() {
super();
let rawGameUrls = (process.env.GAME_URLS || '').split(',');
Expand All @@ -25,7 +27,7 @@ export class GamedigQueryProvider extends PollingProvider {
let results = new Array<ServerResponse>();
for (let g of this.gameUrls) {
results.push(new ServerResponse(g.game,
await query({
await this.gamedig.query({
type: g.game,
host: g.host,
port: g.port,
Expand Down
2 changes: 1 addition & 1 deletion src/services/polling-provider.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Observable, Subject, timer} from 'rxjs';
import { Observable, Subject, timer } from 'rxjs';
import { ServerResponse } from '../models/server-response';

export abstract class PollingProvider {
Expand Down

0 comments on commit 1383a2e

Please sign in to comment.