YouTubePHP Documentation

ChatReader
in package
implements EventEmitterInterface uses EventEmitterTrait

FinalYes

Reads one live chat as it happens, and keeps reading through whatever the network does.

  • Streaming: by default it holds liveChatMessages.stream open, and YouTube pushes each message as it is posted. A stream the server closes is reopened where it left off, with the last nextPageToken, and one that has been silent for five minutes is reopened too, because a connection the network dropped looks exactly like a quiet chat.
  • Polling: liveChatMessages.list at the interval YouTube asks for. It is what the reader falls back to if the stream is refused as unsupported, and it can be chosen outright with mode.
  • History: joining a chat sends its recent history first. Messages posted before the reader joined are not emitted, so a restart does not replay the last few minutes into wherever they are relayed.
  • Quota: before each request it checks the day's quota, reserve kept back. When polling, it slows down when the pace YouTube asks for would run the quota out within budget_hours. When nothing is left but the reserve, it pauses until the reset at midnight Pacific.
  • Dropped connections: it retries with the same back-off as TwitchPHP's chat client, a second to a minute over about five minutes, then every five minutes. reconnect() tries again at once.

Events:

Event Arguments When
chat.item LiveChatMessage Anything new in the chat, whatever its type.
chat.message LiveChatMessage A text message.
chat.superchat LiveChatMessage A Super Chat or Super Sticker.
chat.member LiveChatMessage A new member, a milestone, or gifted memberships.
chat.gift LiveChatMessage A virtual gift.
chat.poll LiveChatMessage A poll, or a change to one.
chat.banned LiveChatMessage A moderator banned someone.
chat.deleted string message id, LiveChatMessage A tombstone: a message that has been deleted.
chat.offline CarbonImmutable The stream went offline. The chat may stay open a while.
chat.ended string why The chat is over. The reader stops.
chat.connected Reading, at first and after every recovery.
chat.disconnected int status, string why Reading stopped.
chat.reconnecting int attempt, float delay Another attempt is coming.
chat.reconnect_failed int attempts The quick retries are spent. Once an outage.
chat.paused CarbonImmutable resumes Only the quota reserve is left. Once a pause.
chat.resumed The quota reset.
chat.slowed float seconds Polling slowed to spread the quota over the day.
chat.mode string mode Streaming was refused, so it polls instead.

YouTube stopped reporting deleted messages as they happen: a deletion shows up only as a tombstone in a later listing, and a moderator's ban arrives as chat.banned.

Tags
link
https://developers.google.com/youtube/v3/live/docs/liveChatMessages/streamList
https://developers.google.com/youtube/v3/live/docs/liveChatMessages/list
since
1.0.0
author

Valithor Obsidion valithor@valgorithms.com

Table of Contents

Interfaces

EventEmitterInterface

Constants

DEFAULTS  : mixed = [ // `stream`, or `poll` to never try streaming...
MODE_POLL  : mixed = 'poll'
MODE_STREAM  : mixed = 'stream'
RETRY_DELAYS  : mixed = [1, 2, 5, 10, 20, 30, 60, 60, 60, 60]
Seconds before each quick retry. After the last, every `keep_trying_every`.
EVENTS  : mixed = [\YouTube\Parts\LiveChatMessageSnippet::TYPE_TE...
Message types, and the event each is emitted as besides `chat.item`.

Properties

$connected  : bool
$ended  : bool
$failureAnnounced  : bool
$failures  : int
Failed attempts in a row.
$generation  : int
Bumped for every attempt, so the callbacks of an abandoned one do nothing.
$historyBefore  : ?float
Messages posted before this Unix time are history. Null once past it.
$idleTimer  : ?TimerInterface
$liveChatId  : string
$mode  : string
$offline  : bool
$options  : array<string, mixed>
$pageToken  : ?string
Where to carry on from, once there is somewhere.
$paused  : bool
$reconnecting  : ?Deferred
Callers of {@see reconnect()} waiting for it.
$running  : bool
$seen  : array<string, true>
$slowed  : bool
$stream  : ?ResponseStream
$streamHeard  : bool
$streamOpenedAt  : float
When the open stream was opened, and whether it has sent anything.
$timer  : ?TimerInterface
$youtube  : YouTube

Methods

__construct()  : mixed
getLiveChatId()  : string
getMode()  : string
`stream`, or `poll` when it was chosen or streaming was refused.
getPageToken()  : ?string
Where the next request carries on from.
hasEnded()  : bool
isConnected()  : bool
reconnect()  : PromiseInterface<string|int, null>
Tries again now, rather than when the next retry is due. Resolves when that attempt works, at once if reading never stopped, and rejects with the reason when it fails. The quota reserve may be spent on it: a person asked. Retrying carries on either way.
start()  : void
Joins the chat and starts reading.
stop()  : void
Stops reading. {@see start()} carries on from where it stopped.
abandon()  : void
Drops whatever is in flight, so its callbacks do nothing.
armIdle()  : void
cancelIdle()  : void
cancelTimer()  : void
end()  : void
The chat is over: nothing more will come.
failed()  : void
fetch()  : void
isHistory()  : bool
Whether a message was posted before the reader joined.
lost()  : void
message()  : void
next()  : void
Schedules the next request.
now()  : float
openStream()  : void
page()  : void
pause()  : void
Only the reserve is left: wait for midnight Pacific.
poll()  : void
pollInterval()  : float
How long to wait before the next poll: what YouTube asks for, or longer if that pace would spend the quota within `budget_hours`, or before it resets if that comes first.
remember()  : void
scheduleRetry()  : void
settleReconnect()  : void
streamClosed()  : void
The open stream closed: by the server's choice, which is carried on from at once, or with an error, which {@see failed()} deals with.
streamingRefused()  : bool
Whether a failure says the stream itself is unavailable, not that the chat is.
succeeded()  : void

Constants

DEFAULTS

public mixed DEFAULTS = [ // `stream`, or `poll` to never try streaming. 'mode' => self::MODE_STREAM, // The parts of each message to ask for. 'part' => ['id', 'snippet', 'authorDetails'], // The language of system messages and currency strings, e.g. `en`. 'hl' => null, // The size, in pixels, of the avatars in `authorDetails`. 'profile_image_size' => null, // Leave out what was posted before the reader joined. 'skip_history' => true, // Seconds before joining that still count as new: clocks disagree a little. 'history_grace' => 10.0, // Seconds between attempts once the quick retries are spent. 'keep_trying_every' => 300.0, // Up to this fraction added to each retry delay, so bots do not retry in step. 'jitter' => 0.2, // Seconds of silence after which a stream is reopened. 'stream_idle' => 300.0, // The slowest the quota may make polling. 'max_poll_interval' => 60.0, // Hours of polling the quota left should last: at the pace YouTube asks // for until the rest would not, then slower. A stream rarely runs until // midnight Pacific, so spreading the quota that far would slow every // stream from its first minute. 'budget_hours' => 6.0, // Message ids remembered, so a reconnect does not repeat one. 'remember' => 2000, // The time, as a Unix timestamp, for tests. 'clock' => null, ]

RETRY_DELAYS

Seconds before each quick retry. After the last, every `keep_trying_every`.

public mixed RETRY_DELAYS = [1, 2, 5, 10, 20, 30, 60, 60, 60, 60]

EVENTS

Message types, and the event each is emitted as besides `chat.item`.

private mixed EVENTS = [\YouTube\Parts\LiveChatMessageSnippet::TYPE_TEXT_MESSAGE_EVENT => 'chat.message', \YouTube\Parts\LiveChatMessageSnippet::TYPE_SUPER_CHAT_EVENT => 'chat.superchat', \YouTube\Parts\LiveChatMessageSnippet::TYPE_SUPER_STICKER_EVENT => 'chat.superchat', \YouTube\Parts\LiveChatMessageSnippet::TYPE_NEW_SPONSOR_EVENT => 'chat.member', \YouTube\Parts\LiveChatMessageSnippet::TYPE_MEMBER_MILESTONE_CHAT_EVENT => 'chat.member', \YouTube\Parts\LiveChatMessageSnippet::TYPE_MEMBERSHIP_GIFTING_EVENT => 'chat.member', \YouTube\Parts\LiveChatMessageSnippet::TYPE_GIFT_MEMBERSHIP_RECEIVED_EVENT => 'chat.member', \YouTube\Parts\LiveChatMessageSnippet::TYPE_GIFT_EVENT => 'chat.gift', \YouTube\Parts\LiveChatMessageSnippet::TYPE_POLL_EVENT => 'chat.poll', \YouTube\Parts\LiveChatMessageSnippet::TYPE_USER_BANNED_EVENT => 'chat.banned']

Properties

$failureAnnounced

private bool $failureAnnounced = false

$failures

Failed attempts in a row.

private int $failures = 0

$generation

Bumped for every attempt, so the callbacks of an abandoned one do nothing.

private int $generation = 0

$historyBefore

Messages posted before this Unix time are history. Null once past it.

private ?float $historyBefore = null

$idleTimer

private ?TimerInterface $idleTimer = null

$liveChatId read-only

private string $liveChatId

$pageToken

Where to carry on from, once there is somewhere.

private ?string $pageToken = null

$reconnecting

Callers of {@see reconnect()} waiting for it.

private ?Deferred $reconnecting = null

$seen

private array<string, true> $seen = []

Recent message ids, oldest first.

$streamOpenedAt

When the open stream was opened, and whether it has sent anything.

private float $streamOpenedAt = 0.0

Methods

__construct()

public __construct(YouTube $youtube, string $liveChatId[, array<string, mixed> $options = [] ]) : mixed
Parameters
$youtube : YouTube
$liveChatId : string
$options : array<string, mixed> = []

See DEFAULTS.

getLiveChatId()

public getLiveChatId() : string
Return values
string

getMode()

`stream`, or `poll` when it was chosen or streaming was refused.

public getMode() : string
Return values
string

getPageToken()

Where the next request carries on from.

public getPageToken() : ?string
Return values
?string

hasEnded()

public hasEnded() : bool
Return values
bool

isConnected()

public isConnected() : bool
Return values
bool

reconnect()

Tries again now, rather than when the next retry is due. Resolves when that attempt works, at once if reading never stopped, and rejects with the reason when it fails. The quota reserve may be spent on it: a person asked. Retrying carries on either way.

public reconnect() : PromiseInterface<string|int, null>
Return values
PromiseInterface<string|int, null>

start()

Joins the chat and starts reading.

public start() : void

stop()

Stops reading. {@see start()} carries on from where it stopped.

public stop() : void

abandon()

Drops whatever is in flight, so its callbacks do nothing.

private abandon() : void

armIdle()

private armIdle(int $generation) : void
Parameters
$generation : int

end()

The chat is over: nothing more will come.

private end(string $why) : void
Parameters
$why : string

failed()

private failed(Throwable $e) : void
Parameters
$e : Throwable

fetch()

private fetch([bool $force = false ]) : void
Parameters
$force : bool = false

Spend the reserve too: a person asked for this.

lost()

private lost(Throwable $e) : void
Parameters
$e : Throwable

next()

Schedules the next request.

private next(float $delay[, bool $force = false ]) : void
Parameters
$delay : float
$force : bool = false

now()

private now() : float
Return values
float

pause()

Only the reserve is left: wait for midnight Pacific.

private pause() : void

pollInterval()

How long to wait before the next poll: what YouTube asks for, or longer if that pace would spend the quota within `budget_hours`, or before it resets if that comes first.

private pollInterval(LiveChatMessageListResponse $page) : float
Parameters
$page : LiveChatMessageListResponse
Return values
float

remember()

private remember(string $id) : void
Parameters
$id : string

settleReconnect()

private settleReconnect([?Throwable $failure = null ]) : void
Parameters
$failure : ?Throwable = null

streamClosed()

The open stream closed: by the server's choice, which is carried on from at once, or with an error, which {@see failed()} deals with.

private streamClosed(bool $withError) : void
Parameters
$withError : bool

streamingRefused()

Whether a failure says the stream itself is unavailable, not that the chat is.

private streamingRefused(Throwable $e) : bool
Parameters
$e : Throwable
Return values
bool
On this page

Search results