Skip to content

Developers ‐ Integrations

Tim Raaymakers edited this page Aug 4, 2024 · 3 revisions

Integrations

Integrations are a key Barricade concept. They allow communities to link Barricade with their RCON services. This is essential for effective use of Barricade, because it is what allows it to actually ban and unban players, but also allows the RCON service to efficiently retrieve information.

Implementing a custom integration

Integrations are associated with a community, and only the owner is priviliged enough to manage their community's integrations. Integrations are managed through Barricade. To connect (or disconnect) one, use the /manage-integrations command.

Client vs. Server

You may have assumed that Barricade will act as the WebSocket server in this relation, given its appeareance of a "central entity", but that is not true. Once an integration is added, it is Barricade that attempts to open a connection and the RCON service will need to be listening for it. This makes Barricade the client and the RCON service the server.

The Integration protocol

To communicate, all requests and responses should follow a protocol. This protocol is built on top of the websocket, meaning that all the data you send and receive using the websocket should be in a given format and follow specific rules.

Handshake

When a new connection is opened, the standard WebSocket handshake is performed with no additional steps. However, Barricade may include an Authorization header with Bearer token (if provided with one).

Requests

All requests are in JSON. They contain an id field, which contains an integer unique to that packet within the scope of its sender and the connection. Typically a simple counter starting at 0 can be used, since it is no issue for the client and server to use the same IDs in their requests.

Furthermore a request contains a request field, which specifies what task is expected from the opposing party. The client and server each have different commands that they can send. Additional arguments can be provided in the optional payload field, which when present must be a JSON object. The arguments required depend on the command and can be found further below.

{
  id: number,
  request: string,
  payload?: object | null
}

Responses

A request should always go paired with a response. A response can be linked to a request by its id field, which mirrors the value of its corresponding request. When a packet is received, first there needs to be figured out whether it is actually a request or response. To differentiate between the two, the request field can be looked at. While a response will still always have a request field, it's value will always be null opposed to a string. If no request or id field is present, the packet is malformed and likely will be ignored.

A response may use the response field to include additional data, which like the request's payload field, is an optional JSON object. There also exists a failed field, but for more info on that see Error Handling.

{
  id: number,
  request: null,
  response?: object | null,
  failed: bool
}

Error Handling

When a request is correctly received but cannot be executed, the receiving party should still return a response. However, they set the failed field to true, and include an error field inside of the response to briefly explain why the request failed.

There is some specific cases that demand specific error messages:

  • A command is sent that the receiver does not recognize: No such command
  • A ban_players command is only partially successful: Could not ban all players
    • Should still include a ban_ids field for the players that were successfully banned.
  • An unban_players command is only partially successful: Could not unban all players
    • Should still include a ban_ids field for the players that were successfully unbanned.

Retrying - When a party receives a response where the failed field is true, the corresponding request should not be resent. It is up to the party processing the request to attempt and retry as it deems necessary before returning an error.

Timeouts - If a sender does not receive a response within a reasonable period of time, an identical request may be resent. Likewise, if the receiving party has already seen a packet with the same ID recently, it is suggested to retransmit the same response as before without reinvoking the command. However, if the receiver was already aware of the request but hadn't yet finished command execution, it can simply ignore the duplicate packet.

List of Client commands

ban_players

Payload:

{
  player_ids: {
    [player_id: string]: string | null
  },
  config: {
    banlist_id: string | null,
    reason: string
  }
}

Response:

{
  ban_ids: {
    [player_id: string]: string
  }
}

Instruct the RCON service to ban the given players.

Expects player_ids to be a list of player IDs that need to be banned mapped to the ban reason. If the ban reason is null, config.reason is used instead.

Returns a new mapping of player IDs to an ID the ban can be recognized by. This could be the player ID again, but ultimately depends on how the RCON service handles its bans.

If not all players could be banned, their IDs should not be returned and the response should fail.

unban_players

Payload:

{
  ban_ids: string[],
  config: {
    banlist_id: string | null
  }
}

Response:

{
  ban_ids: string[]
}

Similar to ban_players, except instructs the RCON service to remove bans instead of adding them.

Takes an array of ban IDs, which are the same IDs the RCON service has given in response to a previous ban_players command.

Returns only the ban IDs of the bans which were successfully removed. If a player was already unbanned (i.e. no ban existed for the given ID), assume a success. If not all bans were successfully removed the command should fail.

new_report

Payload:

{
  created_at: string($iso-8601),
  body: string,
  reasons: string[],
  attachment_urls: string[],
  players: {
    player_id: string,
    player_name: string,
    bm_rcon_url: string | null
  }[]
}

Response: null

Inform a RCON service that a new report was made.

Users do not need to be informed of this; Barricade will already take care of that. However, the RCON service can look if any of the reported players are currently online and subsequently send a more urgent warning to admins (preferably by sending a scan_players command back to Barricade).

Expects all of the report's details. Does not return anything.

List of Server commands

scan_players

Payload:

{
  player_ids: string[]
}

Response: null

Instructs Barricade to check if any of the given players are banned. If so, a warning will be sent to the community's admins with references to all reports made against the player.

RCON services are recommended to use this command every time a player joins to ensure reported players do not join a server unnoticed.