Skip to content

CallowayIsWeird/source-rcon

Repository files navigation

@callowayisweird/source-rcon

Production-grade Source Engine RCON client for Node.js and Bun. Zero runtime dependencies, full TypeScript support.

Install

npm install @callowayisweird/source-rcon

Usage

Basic Connection

import { Rcon } from '@callowayisweird/source-rcon'

const rcon = new Rcon({
  host: '127.0.0.1',
  port: 27015,
  password: 'your_rcon_password',
})

await rcon.connect()

const status = await rcon.execute('status')
console.log(status)

await rcon.disconnect()

Events

const rcon = new Rcon({
  host: '127.0.0.1',
  port: 27015,
  password: 'secret',
})

rcon.on('connect', () => console.log('Connected'))
rcon.on('disconnect', () => console.log('Disconnected'))
rcon.on('error', (err) => console.error('Error:', err))

await rcon.connect()

Auto-Reconnection

const rcon = new Rcon({
  host: '127.0.0.1',
  port: 27015,
  password: 'secret',
  autoReconnect: true,
  maxReconnectAttempts: 5,
  reconnectDelay: 3000,
})

rcon.on('reconnecting', (attempt) => {
  console.log(`Reconnecting... attempt ${attempt}`)
})

await rcon.connect()

Multi-Server Pool

import { RconPool } from '@callowayisweird/source-rcon'

const pool = new RconPool([
  { host: '10.0.0.1', port: 27015, password: 'pass1' },
  { host: '10.0.0.2', port: 27015, password: 'pass2' },
  { host: '10.0.0.3', port: 27015, password: 'pass3' },
])

await pool.connectAll()

// Execute on a specific server
const status = await pool.execute('10.0.0.1:27015', 'status')

// Execute on all servers
const results = await pool.executeAll('status')
for (const [server, response] of results) {
  console.log(`${server}: ${response}`)
}

await pool.disconnectAll()

Permission-Gated RCON

import { Rcon, GatedRcon } from '@callowayisweird/source-rcon'

const rcon = new Rcon({
  host: '127.0.0.1',
  port: 27015,
  password: 'secret',
})

await rcon.connect()

const gated = new GatedRcon(rcon, {
  allowedUsers: ['STEAM_0:1:12345678', 'STEAM_0:1:87654321'],
  permissions: {
    'STEAM_0:1:12345678': ['say *', 'status', 'changelevel *'], // admin
    'STEAM_0:1:87654321': ['say *', 'status'],                   // moderator
  },
  rateLimit: {
    windowMs: 60000,  // 1 minute
    maxCommands: 10,   // max 10 commands per minute
  },
  onExecute: (steamId, command, response) => {
    console.log(`[RCON] ${steamId} executed: ${command}`)
  },
  onBlocked: (steamId, command, reason) => {
    console.warn(`[RCON] Blocked ${steamId}: ${command} (${reason})`)
  },
})

// Will succeed for allowed users with matching permissions
await gated.execute('STEAM_0:1:12345678', 'say Hello everyone!')

// Will throw PermissionDeniedError
await gated.execute('STEAM_0:1:87654321', 'changelevel gm_flatgrass')

Error Handling

import {
  Rcon,
  AuthFailedError,
  ConnectionRefusedError,
  TimeoutError,
  DisconnectedError,
} from '@callowayisweird/source-rcon'

const rcon = new Rcon({
  host: '127.0.0.1',
  port: 27015,
  password: 'secret',
  timeout: 5000,
})

try {
  await rcon.connect()
} catch (err) {
  if (err instanceof AuthFailedError) {
    console.error('Wrong RCON password')
  } else if (err instanceof ConnectionRefusedError) {
    console.error('Server refused connection')
  } else if (err instanceof TimeoutError) {
    console.error('Connection timed out')
  }
}

try {
  await rcon.execute('status')
} catch (err) {
  if (err instanceof DisconnectedError) {
    console.error('Not connected to server')
  } else if (err instanceof TimeoutError) {
    console.error('Command timed out')
  }
}

API Reference

Rcon

Method Description
new Rcon(options) Create a new RCON client
connect() Connect and authenticate
execute(command) Execute a command (queued, sequential)
disconnect() Disconnect from the server
isConnected Whether the client is authenticated

RconOptions

Option Type Default Description
host string required Server hostname or IP
port number required Server RCON port
password string required RCON password
timeout number 5000 Timeout in milliseconds
autoReconnect boolean false Auto-reconnect on disconnect
maxReconnectAttempts number 5 Max reconnection attempts
reconnectDelay number 3000 Delay between reconnect attempts (ms)

Events

Event Arguments Description
connect none Successfully connected and authenticated
disconnect none Disconnected from server
error Error An error occurred
reconnecting number Attempting to reconnect (attempt number)

RconPool

Method Description
new RconPool(servers) Create pool from array of server options
connectAll() Connect to all servers
execute(key, command) Execute on a specific server (host:port)
executeAll(command) Execute on all servers
disconnectAll() Disconnect all servers
get(key) Get the Rcon instance for a server
size Number of servers in the pool

GatedRcon

Method Description
new GatedRcon(rcon, options) Create gated wrapper around an Rcon instance
execute(steamId, command) Execute if permitted, throws PermissionDeniedError if not

Errors

Error Code Description
RconError varies Base error class
AuthFailedError AUTH_FAILED Wrong RCON password
ConnectionError CONNECTION_FAILED Cannot connect to server
ConnectionRefusedError CONNECTION_REFUSED Connection actively refused
TimeoutError TIMEOUT Operation timed out
DisconnectedError DISCONNECTED Not connected to server
BannedError BANNED IP banned after failed auth attempts
PermissionDeniedError PERMISSION_DENIED GatedRcon blocked the command

License

MIT

About

Production-grade Source Engine RCON client. Auto-reconnect, command queue, permission gating.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors