DiscordPHP-BridgeBot Documentation

Connector

One network the bot bridges Discord with.

Everything platform-specific lives behind this: a connector owns its client, its socket, its authentication and its idea of what a room is, and hands the core Incoming messages and Room descriptions. Nothing in the core mentions Twitch or Telegram, and adding a third network is a new package rather than an edit to this one.

A connector is registered with Bot::addConnector(), which calls boot() immediately and start() once Discord is ready — the order matters, because listeners registered in boot() must already be in place when the first message arrives.

What a connector must not do

Never build its own HTTP client for Discord. The bot has exactly one Discord\Http, and that object is where the per-route rate-limit buckets and the concurrency cap live. A second client keeps its own empty bucket table and races the first into 429s against the same token — and 10,000 rejected requests in ten minutes is a Cloudflare ban on the whole host. Use the parts and repositories DiscordPHP hands over; they already route through it.

Its own network is its own business: a connector is expected to pace that side itself, which is what RateLimiter is for.

Tags
author

Valithor Obsidion valithor@discordphp.org

Table of Contents

Methods

boot()  : void
Builds the client and registers everything that must exist before the first message arrives. Called once, when the connector is added.
joined()  : array<int, string>
Every room the connector is currently in.
label()  : string
What to call the network in front of a human: `Twitch`, `Telegram`.
name()  : string
A short, lowercase, stable name — `twitch`, `telegram`.
normalise()  : string|null
Turns however somebody referred to a room into the form this connector addresses it by, or `null` when it is not a room reference at all.
onIncoming()  : void
Registers the handler every inbound message is passed to.
queued()  : int
How many outbound messages are waiting on this connector's own pacing.
relay()  : PromiseInterface<string|int, string|null>
Renders a Discord message for this network and says it.
resolve()  : PromiseInterface<string|int, Room|null>
Looks a room up, resolving to `null` when it does not exist.
send()  : PromiseInterface
Says something in a room, exactly as given.
start()  : PromiseInterface<string|int, mixed>
Connects. Called once Discord is ready and the bridges are known.
stop()  : void
Disconnects cleanly, for shutdown.
surface()  : Surface
What this network's chat can take; see {@see Surface}.
sync()  : array{join: list, part: list}
Joins and leaves whatever the routing table now says, and reports what it did.

Methods

boot()

Builds the client and registers everything that must exist before the first message arrives. Called once, when the connector is added.

public boot(Bot $bot) : void
Parameters
$bot : Bot

joined()

Every room the connector is currently in.

public joined() : array<int, string>

The startup check compares this against what was restored from disk: a join that silently failed leaves a bridge that works in one direction only, which is invisible from the configuration alone.

Return values
array<int, string>

label()

What to call the network in front of a human: `Twitch`, `Telegram`.

public label() : string
Return values
string

name()

A short, lowercase, stable name — `twitch`, `telegram`.

public name() : string

It is not only a label. It keys this connector's bridges in Store, and it is the top-level slash command the connector publishes, so changing it strands both.

Return values
string

normalise()

Turns however somebody referred to a room into the form this connector addresses it by, or `null` when it is not a room reference at all.

public normalise(string $input) : string|null

twitch.tv/Foo and #Foo are both foo; t.me/name is @name. The result is what gets stored, so it must be stable — normalising one way on Monday and another on Tuesday orphans every bridge made before the change.

Parameters
$input : string
Return values
string|null

onIncoming()

Registers the handler every inbound message is passed to.

public onIncoming(callable(Incoming): void $handler) : void

The connector is responsible for setting Incoming::$own on anything the bot itself said. A bridge that repeats its own output is an infinite loop that gets the account banned from both networks within minutes, and only the connector can recognise its own voice.

Parameters
$handler : callable(Incoming): void

queued()

How many outbound messages are waiting on this connector's own pacing.

public queued() : int
Return values
int

relay()

Renders a Discord message for this network and says it.

public relay(string $target, Outgoing $message) : PromiseInterface<string|int, string|null>

The rendering is the connector's because the answer is: IRC cannot carry a newline, Telegram's HTML mode needs exactly three characters escaped, and the limits are 500 and 4096. MessageText holds the parts that are the same everywhere — resolving mentions, budgeting attachment links, truncating on a character boundary — so a connector writes only what is genuinely its own.

Resolves to null when there was nothing worth relaying, which is not a failure: an embed-only message says nothing a chat can repeat.

Parameters
$target : string
$message : Outgoing
Return values
PromiseInterface<string|int, string|null> —

The id of what was said, when the network has them.

resolve()

Looks a room up, resolving to `null` when it does not exist.

public resolve(string $target) : PromiseInterface<string|int, Room|null>

Used by link before wiring anything up — a typo otherwise produces a bridge that silently never works — and by the startup check.

A lookup that failed is not proof a room is gone: reject, or resolve to a Room, rather than resolving to null on a network error.

Parameters
$target : string
Return values
PromiseInterface<string|int, Room|null>

send()

Says something in a room, exactly as given.

public send(string $target, string $text[, array<string, mixed> $options = [] ]) : PromiseInterface

For text this bot composed itself — a command's reply, a notice. Relayed chat goes through relay() instead, which is the one that still has to be rendered.

Parameters
$target : string
$text : string
$options : array<string, mixed> = []

Connector-specific extras — a reply target, a file to attach. Unknown keys are ignored.

Return values
PromiseInterface

start()

Connects. Called once Discord is ready and the bridges are known.

public start() : PromiseInterface<string|int, mixed>

Resolves once the connector can actually send and receive, and rejects when it cannot. That is not a formality: the core joins rooms only after this resolves, reports a network that failed rather than one that merely looks quiet, and refuses to remove stale slash commands unless every connector got here — pruning against a connector that never declared its commands would delete them.

Return values
PromiseInterface<string|int, mixed>

stop()

Disconnects cleanly, for shutdown.

public stop() : void

sync()

Joins and leaves whatever the routing table now says, and reports what it did.

public sync(Links $links) : array{join: list, part: list}

A diff rather than "rejoin everything", so one server's change does not blink every other server's bridge offline.

Parameters
$links : Links
Return values
array{join: list, part: list}
On this page

Search results