Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 25 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,38 @@ on:

jobs:
test:
runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest]
php: ['8.4', '8.5']
include:
- os: windows-latest
php: '8.4'
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
coverage: none
# This library intentionally does not track composer.lock. A fresh checkout
# resolves supported constraints; local reproduction uses its existing lock.
- run: composer validate --no-check-lock --no-check-publish
- run: composer update --no-interaction --no-progress --prefer-dist
- run: vendor/bin/phpunit
- if: matrix.php == '8.4'
run: PHP_CS_FIXER_IGNORE_ENV=1 vendor/bin/php-cs-fixer fix --dry-run --diff
- run: composer verify
- run: composer audit --locked
- if: matrix.os == 'ubuntu-latest' && matrix.php == '8.4'
env:
PHP_CS_FIXER_IGNORE_ENV: '1'
run: php vendor/bin/php-cs-fixer fix --dry-run --diff

lowest-dependencies:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: '8.4'
coverage: none
- run: composer update --prefer-lowest --prefer-stable --no-interaction --no-progress --prefer-dist
- run: composer verify
2 changes: 1 addition & 1 deletion .php-cs-fixer.dist.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

$finder = PhpCsFixer\Finder::create()->in(__DIR__ . '/src')->in(__DIR__ . '/tests');
$finder = PhpCsFixer\Finder::create()->in(__DIR__ . '/src')->in(__DIR__ . '/tests')->in(__DIR__ . '/scripts');

return (new PhpCsFixer\Config())
->setRiskyAllowed(true)
Expand Down
11 changes: 11 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# TwitchPHP contributor guidance

- This is an async ReactPHP library (PHP 8.4+). Follow existing promise and Part/Collection conventions; inspect inherited members before adding client properties or methods.
- Start with `git status --short` and the current diff. Preserve other work, especially dependency constraints and ongoing API fixes. `TwitchPHP-Http` is a separate package; inspect the installed version before assuming a sibling checkout is in use.
- `composer.lock` is intentionally ignored. On a fresh checkout use `composer update`; to reproduce an existing local lock use `composer install`. Do not refresh dependencies simply to hide a failing test. `composer verify` checks manifest/lock consistency, platform requirements, dependency provenance, then the suite without installing anything.
- `composer deps:check` rejects local path dependencies by default. For intentional sibling development, run `composer deps:check -- --allow-local-paths` and the remaining checks separately; report that published dependencies have not been validated. Do not rewrite local path repositories or unrelated Composer edits.
- Use `php vendor/bin/phpunit --filter="ClassName::method"` while fixing a failure. `composer test:api` exercises repository request/response contracts, hydration, token recovery and persistence with synthetic transports. It does not contact Twitch or read `.env`. `composer test` is the broader check. CI covers Ubuntu PHP 8.4/8.5 and Windows PHP 8.4.
- API audits must distinguish expired credentials, missing scopes, wrong token kind, unavailable channel data, and parsing defects. Inspect response shape as well as status. Follow delegated helper calls before reporting an endpoint as missing. Prefer an authoritative operation/path/verb contract over regex counts or scraped prose.
- A live API check is separate from offline verification. Select endpoints explicitly by operation and side effects; include authentication refresh/persistence in that assessment. Never sweep all GETs on the assumption they are read-only. Do not print tokens, Authorization headers, `.env`, or token-bearing URLs. Keep useful checks in `scripts/` or tests, not temporary chat folders.
- Use the repository's php-cs-fixer configuration on touched files. The `tools/` directory is ignored because it holds the documentation builder; put maintained developer checks in `scripts/`.
- For docs changes, inspect `.github/workflows/docs.yml` and exercise its configured `phpdoc.dist.xml` invocation. Docs publish on release, manual dispatch, or a push whose message contains `build docs`; inspect all release workflows before publishing. A local test pass is distinct from a successful CI run or a verified published page.
48 changes: 48 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,54 @@ All notable changes to this project are documented here.

## [Unreleased]

### Fixed

- Recovery and cleanup use promise methods shared by React Promise 2.11 and 3;
the previously advertised 2.11 dependency range could not run API requests.
- EventSub handoffs retain transferred subscriptions and ignore retired sockets.
Fresh sessions replay each subscription once; reconnect attempts continue after
network failures. Welcome and keepalive deadlines detect stalled sockets, and
closing the client cancels pending retries.
- Closing during startup prevents a late authentication or connection result
from marking the client ready or restarting hourly validation.
- App access tokens are reissued on token-related 401s. User grants are validated
on startup and hourly, and reauthorization updates the validated account and
scopes. Revoked grants that cannot recover stop their socket sessions.
- Socket options reach IRC and EventSub as well as HTTP.
- Generic user, channel, reward and conduit saves use their required HTTP methods
and identifier locations. Reward drafts retain writable limits; permanent bans
keep an empty expiry as null. Block-list users retain their ids and logins.
- Generic pagination uses valid defaults; schedules merge segments across pages,
Hype Train reads hydrate the current status model, and stream fetches use user ids.
- iCalendar returns the public text feed without passing through JSON decoding.
Video deletion returns and evicts only confirmed ids. Emotes retain URL templates,
and extension secret requests include the required extension id.
- README filters, OAuth names, namespace imports, auth examples and `.env` casing.
Refresh-token persistence documentation now accounts for tokens that may rotate.

### Added

- `AbstractRepository::nextCursor()` and missing `after` arguments for block lists,
followed streams and extension transactions.
- `Irc::sendMessage()`, with a bounded queue, message rate limits, rejected invalid
input and write-failure feedback. Legacy `say()` reports `chat.message_failed`.
- `Twitch::validateToken()`, `eventsub_options`, `eventsub.subscription_failed`,
`HypeTrainStatus` and `Emote::url()`.
- `EventSub\Webhook` for signed request verification, challenges, revocations and
notification events; `eventSubscriptions->createConduit()` for conduit bindings.
- Recent duplicate notification suppression for WebSockets and webhooks; applications
can persist message ids for deduplication across restarts.
- `EventSub::desiredSubscriptionSpecs()` exposes every channel and version while
`desiredSubscriptions()` retains its existing type-to-condition map.
- Regression tests and CI coverage for the lowest supported dependency versions.

### Changed

- Requires published Collection `^8.4` and React HTTP `^1.11.1`, which contains
fixes for the response-header and chunked-body denial-of-service advisories.
- Generic `fetch()` searches pages where an endpoint has no identifier filter;
provide the resource's required query context through a bound repository.

## [3.4.0] - 2026-09-27

### Fixed
Expand Down
Loading
Loading