DiscordPHP-BridgeBot Documentation

TwitchGateway
in package

FinalYes

Owns the Twitch side of the bridge: one IRC connection, the set of channels it is joined to, and a paced outbound queue.

One connection serves every guild. Two servers following the same streamer share a single JOIN — Links::targets() is already deduplicated — and sync() moves the connection to a new set of channels with a diff rather than a reconnect, so reconfiguring one guild does not interrupt the others.

Tags
author

Valithor Obsidion valithor@valgorithms.com

Table of Contents

Constants

CAPACITY  : mixed = 18
Twitch's chat limit for an account that is not a moderator: 20 messages per 30 seconds, counted across *every* channel it speaks in, not per channel. Kept a little under, since a breach mutes the account.
ECHO_WINDOW  : mixed = 30.0
How long a sent line is remembered for recognising its echo. Twitch delivers a message to the room in well under a second; this only has to outlast a slow network, not a conversation.
MAX_QUEUE  : mixed = 100
How much may wait. A busy Discord channel produces more than Twitch will take — Discord allows a message a second, Twitch fewer than one every 1.6 — so without a bound the backlog grows for as long as the conversation lasts, and is still being played out long after it ended.
PER  : mixed = 30.0

Properties

$budget  : RateLimiter
The account's one send budget.
$clock  : callable(): float
$draining  : bool
$dropped  : int
How many messages were dropped since the backlog last cleared.
$joined  : array<int, string>
$logger  : LoggerInterface
$loop  : LoopInterface
$nick  : string
$onChat  : callable(ChatMessage): void|null
$queues  : array<string, array<int, array{text: string, replyTo: string|null}>>
What is waiting, one queue per channel, in the order channels take turns.
$sent  : array<string, array<int, array{text: string, at: float}>>
What this connection said recently, per channel, oldest first.
$twitch  : Twitch

Methods

__construct()  : mixed
joined()  : array<int, string>
The channels this connection is currently in, lower-case.
listen()  : void
Starts listening. Lines the bridge itself sent are dropped here, since relaying them would bounce every Discord message straight back into Discord.
onChat()  : void
Registers the handler for inbound Twitch chat.
queued()  : int
How many messages are waiting, for logging and health checks.
send()  : void
Queues a message for a Twitch channel.
sync()  : array{join: list, part: list}
Brings the joined set in line with the routing table.
applyJoins()  : void
drain()  : void
Sends whatever the budget allows, one message per channel in turn, then re-arms a timer for the rest. Each channel's own messages stay in order.
isEcho()  : bool
Whether a message is one of this connection's own lines coming back.

Constants

CAPACITY

Twitch's chat limit for an account that is not a moderator: 20 messages per 30 seconds, counted across *every* channel it speaks in, not per channel. Kept a little under, since a breach mutes the account.

public mixed CAPACITY = 18

ECHO_WINDOW

How long a sent line is remembered for recognising its echo. Twitch delivers a message to the room in well under a second; this only has to outlast a slow network, not a conversation.

public mixed ECHO_WINDOW = 30.0

MAX_QUEUE

How much may wait. A busy Discord channel produces more than Twitch will take — Discord allows a message a second, Twitch fewer than one every 1.6 — so without a bound the backlog grows for as long as the conversation lasts, and is still being played out long after it ended.

public mixed MAX_QUEUE = 100

Properties

$dropped

How many messages were dropped since the backlog last cleared.

private int $dropped = 0

$joined

private array<int, string> $joined = []

Channels currently joined, lower-case, no leading '#'.

$onChat

private callable(ChatMessage): void|null $onChat = null

$queues

What is waiting, one queue per channel, in the order channels take turns.

private array<string, array<int, array{text: string, replyTo: string|null}>> $queues = []

One budget is shared by every channel, so a single queue would let one flooded bridge — or one viewer spamming commands — use all of it and push every other channel's messages out of the backlog. Taking turns gives each channel an equal share whenever there is contention.

$sent

What this connection said recently, per channel, oldest first.

private array<string, array<int, array{text: string, at: float}>> $sent = []

Methods

__construct()

public __construct(Twitch $twitch, LoopInterface $loop, LoggerInterface $logger, string $nick[, RateLimiter|null $budget = null ][, callable(): float|null $clock = null ]) : mixed
Parameters
$twitch : Twitch
$loop : LoopInterface
$logger : LoggerInterface
$nick : string
$budget : RateLimiter|null = null
$clock : callable(): float|null = null

Defaults to microtime(true).

joined()

The channels this connection is currently in, lower-case.

public joined() : array<int, string>

Re-established on every start from the routing table, so the startup check compares it against what was restored from disk rather than assuming the JOINs landed.

Return values
array<int, string>

listen()

Starts listening. Lines the bridge itself sent are dropped here, since relaying them would bounce every Discord message straight back into Discord.

public listen() : void

Only those lines, though — not everything from this account. The bot speaks as the host's own Twitch account, so a message from it is usually the host typing in chat, and that is exactly what the bridge is for. Twitch does not send a connection its own messages back; a line from this account that matches one just sent is dropped all the same, in case something ever does.

onChat()

Registers the handler for inbound Twitch chat.

public onChat(callable $handler) : void
Parameters
$handler : callable

queued()

How many messages are waiting, for logging and health checks.

public queued() : int
Return values
int

send()

Queues a message for a Twitch channel.

public send(string $channel, string $text[, string|null $replyTo = null ]) : void

Never sends around the budget: Twitch mutes the account for 30 minutes if the send limit is exceeded, so everything goes through the one account-wide bucket, whichever channel it is for.

Command replies come through here too, not just relayed chat. Both speak as the same account against the same limit, and two senders that each stay under it will still breach it together.

Parameters
$channel : string
$text : string
$replyTo : string|null = null

An IRCv3 message id to thread the reply onto.

sync()

Brings the joined set in line with the routing table.

public sync(Links $links) : array{join: list, part: list}
Parameters
$links : Links
Return values
array{join: list, part: list} —

what actually changed

applyJoins()

private applyJoins(array<int, string> $logins) : void
Parameters
$logins : array<int, string>

drain()

Sends whatever the budget allows, one message per channel in turn, then re-arms a timer for the rest. Each channel's own messages stay in order.

private drain() : void

isEcho()

Whether a message is one of this connection's own lines coming back.

private isEcho(ChatMessage $message) : bool

Each sent line can be matched once, so the host saying the same thing a moment later is still relayed.

Parameters
$message : ChatMessage
Return values
bool
On this page

Search results