DiscordPHP-BridgeBot Documentation

WebhookDelivery
in package

FinalYes

Posts another network's chat into Discord.

Uses a webhook so each relayed line carries the speaker's own name and avatar instead of arriving as a wall of identical bot messages. That is not only cosmetic: webhook messages carry a webhook_id, which is how the relay recognises its own output and refuses to send it back out again.

Webhooks need Manage Webhooks. When that is missing — or creation fails for any other reason — delivery falls back to an ordinary bot message with the author's name inline, so a misconfigured server degrades to an uglier bridge rather than a silent one.

Staying inside Discord's budget

Two things here exist because of the rate limits rather than the feature:

  • Every send goes through OutboundPacer. One message on a busy network fans out to every Discord channel following that room, and with more than one connector installed they all draw on one token's budget.
  • A channel we cannot create a webhook in is remembered. Without that memo, a server that never granted Manage Webhooks costs one rejected request per relayed message — and 10,000 rejections in ten minutes is a Cloudflare ban on the whole host, not a throttle.

Nothing here builds an HTTP client. Webhook::execute() and Channel::sendMessage() both go through the one Discord\Http the bot owns, which is where the per-route buckets live.

Tags
author

Valithor Obsidion valithor@discordphp.org

Table of Contents

Constants

USERNAME_LIMIT  : mixed = 80
Discord rejects a webhook username longer than this.
VIA_BOT  : mixed = 'bot'
VIA_WEBHOOK  : mixed = 'webhook'
How a delivered copy was posted, which decides how it can be edited.

Properties

$cache  : array<string, Webhook|false>
$discord  : Discord
$pacer  : OutboundPacer
$webhookName  : string

Methods

__construct()  : mixed
deliver()  : PromiseInterface<string|int, array{message_id: string, via: string}>
Delivers one message to one Discord channel, and says where it landed.
edit()  : PromiseInterface
Rewrites a copy this delivery posted, to what the original now says.
forget()  : void
Forgets a channel's cached webhook — call when delivery starts failing.
queued()  : int
How many deliveries are waiting on Discord's budget.
safeUsername()  : string
Discord rejects webhook usernames containing "discord", and caps them at 80 characters. A display name from another network can be either, and the bridge should not drop a message over it.
body()  : MessageBuilder
The part of a message both paths share.
create()  : PromiseInterface<string|int, Webhook>
escape()  : string
Neutralises Discord markdown in a name shown in the fallback path.
fallback()  : PromiseInterface<string|int, array{message_id: string, via: string}>
An ordinary bot message, for a channel the bot cannot create a webhook in. Uglier — every line carries the bot's name and picture, so the author has to be written into the text — but never silent.
webhookFor()  : PromiseInterface<string|int, Webhook>

Constants

USERNAME_LIMIT

Discord rejects a webhook username longer than this.

public mixed USERNAME_LIMIT = 80

VIA_WEBHOOK

How a delivered copy was posted, which decides how it can be edited.

public mixed VIA_WEBHOOK = 'webhook'

Properties

$cache

private array<string, Webhook|false> $cache = []

Channel id => webhook, or false when we know we can't have one.

Methods

__construct()

public __construct(Discord $discord, OutboundPacer $pacer[, string $webhookName = 'Bridge' ]) : mixed
Parameters
$discord : Discord
$pacer : OutboundPacer
$webhookName : string = 'Bridge'

deliver()

Delivers one message to one Discord channel, and says where it landed.

public deliver(Channel $channel, string $author, string|null $text[, string|null $avatarUrl = null ][, string $suffix = '' ][, array{filename: string, content: string}|null $file = null ]) : PromiseInterface<string|int, array{message_id: string, via: string}>

allowed_mentions is empty on every path: this text came from another network and is untrusted, and somebody typing @everyone there must not ping a Discord server. Neutering it at the API rather than by mangling the text means they still read as having typed it.

The webhook is executed with wait, so Discord answers with the message it created. That id is what lets a later edit on the other network find this copy; without it every edit would have to be posted as a second message.

Parameters
$channel : Channel
$author : string
$text : string|null
$avatarUrl : string|null = null
$suffix : string = ''

Appended to the display name, so it is obvious a relayed line is not a Discord account.

$file : array{filename: string, content: string}|null = null

A file to upload with it.

Return values
PromiseInterface<string|int, array{message_id: string, via: string}>

edit()

Rewrites a copy this delivery posted, to what the original now says.

public edit(Channel $channel, string $messageId, string $via, string $author, string $text[, string $suffix = '' ]) : PromiseInterface

A webhook message is edited through the webhook that posted it; a fallback message through the bot, which authored it. Either way it goes through the pacer, because an edit spends the same channel's budget as a send.

Parameters
$channel : Channel
$messageId : string
$via : string
$author : string
$text : string
$suffix : string = ''
Return values
PromiseInterface

forget()

Forgets a channel's cached webhook — call when delivery starts failing.

public forget(Channel $channel) : void
Parameters
$channel : Channel

queued()

How many deliveries are waiting on Discord's budget.

public queued() : int
Return values
int

safeUsername()

Discord rejects webhook usernames containing "discord", and caps them at 80 characters. A display name from another network can be either, and the bridge should not drop a message over it.

public static safeUsername(string $author[, string $suffix = '' ]) : string
Parameters
$author : string
$suffix : string = ''
Return values
string

body()

The part of a message both paths share.

private body(string|null $text[, array{filename: string, content: string}|null $file = null ]) : MessageBuilder
Parameters
$text : string|null
$file : array{filename: string, content: string}|null = null
Return values
MessageBuilder

create()

private create(Channel $channel) : PromiseInterface<string|int, Webhook>
Parameters
$channel : Channel
Return values
PromiseInterface<string|int, Webhook>

escape()

Neutralises Discord markdown in a name shown in the fallback path.

private static escape(string $text) : string
Parameters
$text : string
Return values
string

fallback()

An ordinary bot message, for a channel the bot cannot create a webhook in. Uglier — every line carries the bot's name and picture, so the author has to be written into the text — but never silent.

private fallback(Channel $channel, string $author, string|null $text, string $suffix, array{filename: string, content: string}|null $file) : PromiseInterface<string|int, array{message_id: string, via: string}>
Parameters
$channel : Channel
$author : string
$text : string|null
$suffix : string
$file : array{filename: string, content: string}|null
Return values
PromiseInterface<string|int, array{message_id: string, via: string}>

webhookFor()

private webhookFor(Channel $channel) : PromiseInterface<string|int, Webhook>
Parameters
$channel : Channel
Return values
PromiseInterface<string|int, Webhook>
On this page

Search results