romanzipp / laravel-twitch Goto Github PK
View Code? Open in Web Editor NEWTwitch Helix API PHP Wrapper for Laravel
Home Page: https://packagist.org/packages/romanzipp/laravel-twitch
License: MIT License
Twitch Helix API PHP Wrapper for Laravel
Home Page: https://packagist.org/packages/romanzipp/laravel-twitch
License: MIT License
Twitch added new Endpoints for Channel Points to the Helix namespace:
https://dev.twitch.tv/docs/api/reference#create-custom-rewards
https://dev.twitch.tv/docs/api/reference#delete-custom-reward
https://dev.twitch.tv/docs/api/reference#get-custom-reward
https://dev.twitch.tv/docs/api/reference#get-custom-reward-redemption
https://dev.twitch.tv/docs/api/reference#update-custom-reward
https://dev.twitch.tv/docs/api/reference#update-redemption-status
Hi, I'm getting this error when I try to use the functions in the examples:
Argument 1 passed to romanzipp\Twitch\Result::__construct() must be an instance of GuzzleHttp\Psr7\Response, null given, called in ...\vendor\romanzipp\laravel-twitch\src\Twitch.php on line 258
composer show -i
beyondcode/laravel-dump-server 1.2.2 Symfony Var-Dump Server for Laravel
dnoegel/php-xdg-base-dir 0.1 implementation of xdg base directory specification for php
doctrine/inflector v1.3.0 Common String Manipulations with regard to casing and singular/plural ru...
doctrine/instantiator 1.1.0 A small, lightweight utility to instantiate objects in PHP without invok...
doctrine/lexer v1.0.1 Base library for a lexer that can be used in Top-Down, Recursive Descent...
dragonmantank/cron-expression v2.2.0 CRON for PHP: Calculate the next or previous run date and determine if a...
egulias/email-validator 2.1.6 A library for validating emails against several RFCs
erusev/parsedown 1.7.1 Parser for Markdown.
fideloper/proxy 4.0.0 Set trusted proxies for Laravel
filp/whoops 2.2.1 php error handling for cool kids
fzaninotto/faker v1.8.0 Faker is a PHP library that generates fake data for you.
guzzlehttp/guzzle 6.3.3 Guzzle is a PHP HTTP client library
guzzlehttp/promises v1.3.1 Guzzle promises library
guzzlehttp/psr7 1.4.2 PSR-7 message implementation that also provides common utility methods
hamcrest/hamcrest-php v2.0.0 This is the PHP port of Hamcrest Matchers
jakub-onderka/php-console-color v0.2
jakub-onderka/php-console-highlighter v0.3.2
laravel/framework v5.7.8 The Laravel Framework.
laravel/tinker v1.0.7 Powerful REPL for the Laravel framework.
league/flysystem 1.0.46 Filesystem abstraction: Many filesystems, one API.
mockery/mockery 1.2.0 Mockery is a simple yet flexible PHP mock object framework
monolog/monolog 1.23.0 Sends your logs to files, sockets, inboxes, databases and various web se...
myclabs/deep-copy 1.8.1 Create deep copies (clones) of your objects
nesbot/carbon 1.34.0 A simple API extension for DateTime.
nikic/php-parser v4.0.4 A PHP parser written in PHP
nunomaduro/collision v2.1.0 Cli error handling for console/command-line PHP applications.
opis/closure 3.1.1 A library that can be used to serialize closures (anonymous functions) a...
paragonie/random_compat v9.99.99 PHP 5.x polyfill for random_bytes() and random_int() from PHP 7
phar-io/manifest 1.0.3 Component for reading phar.io manifest information from a PHP Archive (P...
phar-io/version 2.0.1 Library for handling version information and constraints
phpdocumentor/reflection-common 1.0.1 Common reflection classes used by phpdocumentor to reflect the code stru...
phpdocumentor/reflection-docblock 4.3.0 With this component, a library can provide support for annotations via D...
phpdocumentor/type-resolver 0.4.0
phpspec/prophecy 1.8.0 Highly opinionated mocking framework for PHP 5.3+
phpunit/php-code-coverage 6.0.8 Library that provides collection, processing, and rendering functionalit...
phpunit/php-file-iterator 2.0.2 FilterIterator implementation that filters files based on a list of suff...
phpunit/php-text-template 1.2.1 Simple template engine.
phpunit/php-timer 2.0.0 Utility class for timing
phpunit/php-token-stream 3.0.0 Wrapper around PHP's tokenizer extension.
phpunit/phpunit 7.4.0 The PHP Unit Testing framework.
psr/container 1.0.0 Common Container Interface (PHP FIG PSR-11)
psr/http-message 1.0.1 Common interface for HTTP messages
psr/log 1.0.2 Common interface for logging libraries
psr/simple-cache 1.0.1 Common interfaces for simple caching
psy/psysh v0.9.8 An interactive shell for modern PHP.
ramsey/uuid 3.8.0 Formerly rhumsaa/uuid. A PHP 5.4+ library for generating RFC 4122 versio...
romanzipp/laravel-twitch 1.0.18 Twitch PHP Wrapper for Laravel
sebastian/code-unit-reverse-lookup 1.0.1 Looks up which function or method a line of code belongs to
sebastian/comparator 3.0.2 Provides the functionality to compare PHP values for equality
sebastian/diff 3.0.1 Diff implementation
sebastian/environment 3.1.0 Provides functionality to handle HHVM/PHP environments
sebastian/exporter 3.1.0 Provides the functionality to export PHP variables for visualization
sebastian/global-state 2.0.0 Snapshotting of global state
sebastian/object-enumerator 3.0.3 Traverses array structures and object graphs to enumerate all referenced...
sebastian/object-reflector 1.1.1 Allows reflection of object attributes, including inherited and non-publ...
sebastian/recursion-context 3.0.0 Provides functionality to recursively process PHP variables
sebastian/resource-operations 2.0.1 Provides a list of PHP built-in functions that operate on resources
sebastian/version 2.0.1 Library that helps with managing the version number of Git-hosted PHP pr...
swiftmailer/swiftmailer v6.1.3 Swiftmailer, free feature-rich PHP mailer
symfony/console v4.1.6 Symfony Console Component
symfony/css-selector v4.1.6 Symfony CssSelector Component
symfony/debug v4.1.6 Symfony Debug Component
symfony/event-dispatcher v4.1.6 Symfony EventDispatcher Component
symfony/finder v4.1.6 Symfony Finder Component
symfony/http-foundation v4.1.6 Symfony HttpFoundation Component
symfony/http-kernel v4.1.6 Symfony HttpKernel Component
symfony/polyfill-ctype v1.9.0 Symfony polyfill for ctype functions
symfony/polyfill-mbstring v1.9.0 Symfony polyfill for the Mbstring extension
symfony/polyfill-php72 v1.9.0 Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions
symfony/process v4.1.6 Symfony Process Component
symfony/routing v4.1.6 Symfony Routing Component
symfony/translation v4.1.6 Symfony Translation Component
symfony/var-dumper v4.1.6 Symfony mechanism for exploring and dumping PHP variables
theseer/tokenizer 1.1.0 A small library for converting tokenized PHP source code into XML and po...
tijsverkoyen/css-to-inline-styles 2.2.1 CssToInlineStyles is a class that enables you to convert HTML-pages/file...
vlucas/phpdotenv v2.5.1 Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SE...
webmozart/assert 1.3.0 Assertions to validate method input/output with nice error messages.
Twitch added an endpoint for Get Followed Streams
with the corresponding scope user:read:follows
See: https://dev.twitch.tv/docs/api/reference/#get-followed-streams
I'm trying to figure out how to get the total followers count.
I'm making this call:
$result = $twitch->getUsersFollows(['to_id' => 23161357, 'first' => 1]);
How can I now get the total value the Twitch API is returning shown here:
https://dev.twitch.tv/docs/api/reference#get-users-follows
Hey guys,
I'm trying to use this package to check if a user has subscribed to a channel.
To test Eventsub, I did an endpoint to subscribe to receive the event when the Twitch channel get a new follower:
$payload = [
'type' => 'channel.follow',
'version' => '1',
'condition' => [
'broadcaster_user_id' => '12826', // twitch
],
'transport' => [
'method' => 'webhook',
'callback' => config('app.url') . '/v1/twitch/eventsub/webhook',
]
];
$result = $twitch->subscribeEventSub([], $payload);
dd($result);
When Twitch calls my webhook /v1/twitch/eventsub/webhook
, these are the headers I get (I replaced sensitive informations just in case):
Connection: upgrade
Content-Length: 420
Content-Type: application/json
Host: example.com:443
Twitch-Eventsub-Message-Id: sdfsdf-sdff-1234-1234-1234azer1234
Twitch-Eventsub-Message-Retry: 0
Twitch-Eventsub-Message-Signature: sha256=sdujfgdssdfgkjdhgldfgfdg
Twitch-Eventsub-Message-Timestamp: 2021-03-19T23:51:24.637747359Z
Twitch-Eventsub-Message-Type: webhook_callback_verification
Twitch-Eventsub-Subscription-Type: channel.follow
Twitch-Eventsub-Subscription-Version: 1
Upgrade-Insecure-Requests: 1
User-Agent: Go-http-client/1.1
X-Expose-Request-Id: 999999fe299db
X-Exposed-By: Expose unreleased
X-Forwarded-For: 12.34.56.78
X-Forwarded-Proto: https
X-Original-Host: example.com
And here is the error I have, from romanzipp\Twitch\Objects\EventSubSignature
:
Unable to extract timestamp and signatures from header
romanzipp\Twitch\Exceptions\SignatureVerificationException: Unable to extract timestamp and signatures from header in /laravel/vendor/romanzipp/laravel-twitch/src/Objects/EventSubSignature.php:28
It seems Twitch-Eventsub-Message-Timestamp
is no longer a timestamp but a date with nanoseconds.
Maybe I don't use the package correctly, feel free to correct me if necessary.
If not, please could you fix that?
Thank you!
Example
- public function getStreamsByUserId(int $id, array $parameters, Paginator $paginator)
+ public function getStreamsByUserId(int $id, array $parameters = [], Paginator $paginator = null)
I plan to login via Twitch.
I have a login view.
public function login()
{
return view('auth.login', [
'authorize_url' => $this->twitch->getOAuthAuthorizeUrl($responseType = 'code')
]);
}
I can get the code.
public function callback(Request $request)
{
Log::info($request->code);
}
But how do I get the information like email address, Twitch username & Twitch-ID from this user?
When I try to poll streams using the getStreams() method, after iterating over about 40.000 results I get the following error
I added a logger to debug the response and this is what I got:
[2020-05-07T16:16:40.964227+00:00] guzzle-log.NOTICE: RESPONSE: NULL NULL cURL error 0: The cURL request was retried 3 times and did not succeed. The most likely reason for the failure is that cURL was unable to rewind the body of the request and subsequent retries resulted in the same error. Turn on the debug option to see what went wrong. See https://bugs.php.net/bug.php?id=47204 for more information. (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) - NULL - NULL [] []
Format: RESPONSE: {code} {phrase} {error} - {res_headers} - {res_body}
Why do we have to define a cache driver? It is already defined in the store configuration.
/*
* The cache driver to use for storing Client Credentials.
*/
'cache_driver' => null,
The time zone in laravel is specified in Moscow, in" tolerance " it is specified in 180,but the question is what should be specified in minutes or in seconds?
Sometimes I've got an error in this row of code
$result = $twitch->getStreams($params, isset($result) ? $result->next() : null);
Undefined property: stdClass::$cursor
Hello,
how can i implement other webhooks explained here: https://dev.twitch.tv/docs/api/webhooks-reference
i need moderator changes and subscriptions. will there be a new version soon?
In February 2023, IRC commands will be deprecated from non-twitch managed IRC.
We were instructed by Twitch Dev to use the new endpoint.
https://dev.twitch.tv/docs/api/reference/#send-chat-announcement
c734c5b is missing a release, causing the error to occur under certain circumstances - specifically, ide-helper:generate from https://github.com/barryvdh/laravel-ide-helper
PHP Fatal error: Declaration of romanzipp\Twitch\Traits\UsersTrait::withToken() must be compatible with romanzipp\Twitch\Traits\ExtentionsTrait::withToken(string $token)
Twitch released a new product called "EventSub", which allows subscribing to event notifications via multiple different transport types (including WebHooks):
https://dev.twitch.tv/docs/eventsub
This introduces new Endpoints to the Helix namespace.
Hi there,
I can't find a way to get an App Token with the package. I think this method in romanzipp\Twitch\Trait\OAuthTrait could be useful to do that :
public function getAppToken(array $scopes = []): Result
{
$parameters = [
'client_id' => $this->getClientId(),
'client_secret' => $this->getClientSecret($scopes),
'grant_type' => "client_credentials",
'scope' => $this->buildScopes($scopes)
];
return $this->post(self::OAUTH_BASE_URI . 'token', $parameters);
}
I'm referring with https://dev.twitch.tv/docs/authentication/getting-tokens-oauth/#oauth-client-credentials-flow
Starting May 1, 2020 Bearer Tokens become mandatory.
Requests using only Client IDs will be dropped.
https://discuss.dev.twitch.tv/t/requiring-oauth-for-helix-twitch-api-endpoints/23916
I would appreciate a support for automatic requests of app access token, when no token is provided.
In OAuth Authorizations there's a field to specify if you want to force user verification, as Twitch docs says:
Specifies whether the user should be re-prompted for authorization. If this is
true
, the user always is prompted to confirm authorization. This is useful to allow your users to switch Twitch accounts, since there is no way to log users out of the API. Default:false
(a given user sees the authorization page for a given set of scopes only the first time through the sequence).
This is not working propertly as PHP is converting the "true" and "false" values to the integers 1 and 0 and what Twitch expects are values as the strings true
or false
.
Fatal error: Allowed memory size of 1610612736 bytes exhausted (tried to allocate 4096 bytes) in phar:///usr/local/bin/composer/src/Composer/DependencyResolver
/RuleWatchGraph.php on line 52
So after running:
composer require romanzipp/laravel-twitch
I had a memory limit error and I ran this line to fix it:
COMPOSER_MEMORY_LIMIT=-1 composer require huddledigital/zendesk-laravel
The TMI endpoint for getting chatters will be deprecated, in favor of a new API endpoint.
Old endpoint was a URL and replacing "twitchdev" with the username of the user, which would return a list of chatters.
https://tmi.twitch.tv/group/user/twitchdev/chatters
New endpoint:
https://dev.twitch.tv/docs/api/reference/#get-chatters
Laravel 8.83.14
romanzipp/laravel-twitch 4.4
Getting a Invalid content type response from Twitch CLI
twitch event verify-subscription subscribe -F http://localhost:8000/webhooks/twitch/eventsub/ -s 5f1a6e7cd2e7137ccf9e15b2f43fe63949eb84b1db83c1d5a867dc93429de4e4
โ Valid response. Received challenge 52c24de5-e8fb-1d6a-e52e-a8c787670fff in body
โ Invalid content-type header. Received type text/html with charset UTF-8. Expecting text/plain.
โ Valid status code. Received status 200
After revising the code to a manual response, all pass.
โ Valid response. Received challenge a9298bcd-e8bf-0327-dc0b-e24d3bfc3171 in body
โ Valid content-type header. Received type text/plain with charset UTF-8
โ Valid status code. Received status 200
EventSubController.php (original): https://pastebin.com/gQbFaYcX
EventSubController.php (revised): https://pastebin.com/ga3K0jUX
--
Not sure if the aforementioned is related, but also in production env. the status of the event sub is "webhook_callback_verification_failed" with original/revised versions.
Any assistance is appreciated, thanks!
public function getSubscriptions(array $parameters = array (), Paginator $paginator = NULL)
I think there is twist, the function getSubscriptions() is not working, I get an error message: Missing required parameter "broadcaster_id.
Twitch seems to removed this endpoint in https://dev.twitch.tv/docs/api/reference/#get-broadcaster-subscriptions. There is no method to check the users subscription list at the moment.
The path to Get All Stream Tags
endpoint is wrong, - it should be tags/streams
instead of streams/tags
, please see the doc https://dev.twitch.tv/docs/api/reference#get-all-stream-tags
Hello,
I couldn't get the current user using only the oauth token, according to documentations if the getUsers endpoint is called with no parameters it will return the current user, but since the parameters on you implementation was required I couldn't get it working.
removing the line:
if ( ! array_key_exists('login', $parameters) && ! array_key_exists('id', $parameters)) { throw new InvalidArgumentException('Parameter required missing: name or id'); }
from UsersTrait.php getUsers method solved this for me with an empty array as parameter.
Laravel Version: 9.2
Laravel-Twitch Version: 4.4
When creating a Webhook subscription the EventSubController is constructed but the handleWebhook Method is not called.
web.php
Route::post('/callback/twitch', [EventSubController::class, 'handleWebhook']);
Route::get('/creating', function()
{
$twitch = new Twitch;
$result = $twitch->subscribeEventSub([], [
'type' => EventSubType::CHANNEL_FOLLOW,
'version' => '1',
'condition' => [
'broadcaster_user_id' => '<id>',
],
'transport' => [
'method' => 'webhook',
'callback' => 'https://<URL>/callback/twitch',
]
]);
Log::info("Creating!!!");
var_dump($result->data());
});
In EventSub Controller i made small changes:
class EventSubController extends Controller
{
public function __construct()
{
Log::info("EventSub:__construct()");
if (config('twitch-api.eventsub.secret')) {
Log::info("If Case");
$this->middleware(VerifyEventSubSignature::class);
}
}
[...]
public function handleWebhook(Request $request): Response
{
Log::info("handleWebhook");
==> the handleWebhook
is not displayed
and the Log then shows the Following
[2022-06-02 12:20:09] local.INFO: Creating!!!
[2022-06-02 12:20:11] local.INFO: EventSub:__construct()
[2022-06-02 12:20:11] local.INFO: If Case
[2022-06-02 12:20:11] local.INFO: Leaving Construct
[2022-06-02 12:20:21] local.INFO: EventSub:__construct()
[2022-06-02 12:20:21] local.INFO: If Case
[2022-06-02 12:20:21] local.INFO: Leaving Construct
and the verification status goes to failed after four tries.
Do i miss something?
Did i make mistakes?
When I use buildWebhookTopic in new lib version I've got an error 400 Bed Request.
I've spent a some debug execution and reason that you have double json_encode
One of them in
if (null !== $body) {
$jsonBody = json_encode($body);
}
and another then you call a Guzzle request, cause 'json' param in Guzzle
request must be an array. So Guzzle
by himself encode data.
I'm going to keep this short, privatising "status" does nothing but add more work on someone using your package, for example getting a users subscribers, $var->status == 200/404, why make it more of a pain? Honestly......
Hello,
Just getting started with this package and it's working nicely so far. I see in the pull requests you are working on adding some missing endpoints, I have one more that I would love for you to add.
It's the oauth validate endpoint for validating tokens (More info here).
Thanks for your work
-Casey
I have the feeling that the oauth client credentials cache does not renew expired keys.
I have the problem almost every month that I get the response Invalid OAuth token
from the Twitch API.
Unfortunately I could not look at it. Workaround was: Change cache key.
composer.json
"require": {
"php": ">=7.0",
- "laravel/framework": "^5.3",
+ "illuminate/support": "^5.3",
"guzzlehttp/guzzle": "^6.2@dev"
},
Can you add support for laravel 7? Thanks.
Hey guys,
I'm trying to use this package to check if a user has subscribed to a channel.
To test Eventsub, I did an endpoint to subscribe and receive the event when the Twitch channel get a new follower. Here is my code:
routes/web.php
...
Route::post('twitch/eventsub/webhook', 'EventSubController@handleWebhook');
Route::get('twitch/test', 'TwitchController@test');
EventSubController.php
<?php
namespace App\Http\Controllers\Web\Twitch;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use romanzipp\Twitch\Http\Controllers\EventSubController as BaseController;
class EventSubController extends BaseController
{
/**
* Handle a EventSub notification call.
*
* @param array $payload
*
* @return Response
*/
protected function handleNotification(array $payload): Response
{
return $this->successMethod();
}
/**
* Handle a EventSub revocation call.
*
* @param array $payload
*
* @return Response
*/
protected function handleRevocation(array $payload): Response
{
return $this->successMethod();
}
}
TwitchController.php
<?php
namespace App\Http\Controllers\Web\Twitch;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use romanzipp\Twitch\Enums\EventSubType;
use romanzipp\Twitch\Enums\GrantType;
use romanzipp\Twitch\Twitch;
class TwitchController extends Controller
{
public function test(Request $request)
{
$twitch = new Twitch;
$result = $twitch->getOAuthToken(null, GrantType::CLIENT_CREDENTIALS, [
'user:read:email',
'user:edit:follows',
'channel:read:subscriptions'
]);
$token = $result->data()->access_token;
$payload = [
'type' => EventSubType::CHANNEL_FOLLOW,
'version' => '1',
'condition' => [
'broadcaster_user_id' => '12826', // twitch
],
'transport' => [
'method' => 'webhook',
'callback' => config('app.url') . '/twitch/eventsub/webhook',
]
];
$result = $twitch->withToken($token)->subscribeEventSub([], $payload);
dd($payload, $result);
}
}
When I call /twitch/test
everything is fine. The subscription status is webhook_callback_verification_pending
.
Next the endpoint /twitch/eventsub/webhook
is called. In my log file, I can see handleWebhookCallbackVerification
is called, and return challenge
.
But the webhook is called again, and after the subscription status is webhook_callback_verification_failed
.
Please can you tell me what's wrong here ?
Thank you !
Hello, I am a beginner of Laravel.
I would like to create a "Connect with Twich" button. The goal is to retrieve the twitch id and twitch username of the user who wants to connect.
I followed your documentation but I cannot create my controller using your code.
I have correctly set the "clientid", "clientsecret", "redirect" information.
Can you explain the procedure to me in detail?
I work with Laravel 8.
Thank you so much.
Twitch switched their game lookup from Giant Bomb to IGDB (which they bought a while ago).
See https://twitter.com/TwitchSupport/status/1310625492274470912
With that switch, IGDB's API now uses Twitch' OAuth2 Tokens (https://medium.com/igdb/igdb-api-v4-is-coming-6ba97874edbc).
I think, it would be nice, if IGDB (which is now technically part of Twitch) could be integrated into this package.
Generating and handling Bearer Tokens for the same authentication system twice, seems a like a big overhead.
Additionally, by integrating the IGDB API, more information regarding the games, returned by Twitch's API, can be obtained without handling another authentication system.
maybe is a dumb question but...
how can i create a secret for my EventSub? i need to get it from twitch or just i need to write a simple word like a password?
Can you update the require version of laravel. Thanks.
The legacyRefreshToken
method will soon no longer work or is no longer working. Therefore ASAP the new endpoint id.twitch.tv
must be integrated.
Any instances of https://api.twitch.tv/kraken/oauth2 should be changed to https://id.twitch.tv/oauth2 before the end of 2018.
https://discuss.dev.twitch.tv/t/oauth-kraken-migration/14606
PHP 7 has been decommissioned and security patches will be delivered November 28, 2022: https://www.php.net/supported-versions.php
After that, I believe PHP 7 support can be dropped to make use of the new PHP 8 features.
First of all, thanks for the amazing package.
When I set app.php's zime zone to my local time zone, the eventsub webhook URL keeps throwing SignatureVerificationException
with the message Timestamp outside the tolerance zone
, it works when I set it back to Laravel's default though.
Is this perhaps a problem on my side?
composer.json
"require": {
"php": ">=7.0",
"laravel/framework": "^5.3",
- "guzzlehttp/guzzle": "^6.2@dev"
+ "guzzlehttp/guzzle": "^6.3"
},
How do I get the OAuth token with a given "code"? The "token" response here is NULL
I'm not sure how I'm supposed to parse the data to get the token out?
From within Laravel I'm doing the following:
twitch::setClientId('REDACTED');
twitch::setClientSecret('REDACTED');
$r=twitch::getOAuthToken($code);
var_dump($r);
The response is:
object(romanzipp\Twitch\Result)#360 (9) {
["success"]=>
bool(true)
["exception"]=>
NULL
["data"]=>
array(0) {
}
["total"]=>
int(0)
["status"]=>
int(200)
["pagination"]=>
NULL
["paginator"]=>
object(romanzipp\Twitch\Helpers\Paginator)#344 (2) {
["pagination":"romanzipp\Twitch\Helpers\Paginator":private]=>
NULL
["action"]=>
NULL
}
["response"]=>
object(GuzzleHttp\Psr7\Response)#355 (6) {
["reasonPhrase":"GuzzleHttp\Psr7\Response":private]=>
string(2) "OK"
["statusCode":"GuzzleHttp\Psr7\Response":private]=>
int(200)
["headers":"GuzzleHttp\Psr7\Response":private]=>
array(7) {
["Date"]=>
array(1) {
[0]=>
string(29) "Mon, 02 Sep 2019 19:41:34 GMT"
}
["Content-Type"]=>
array(1) {
[0]=>
string(16) "application/json"
}
["Content-Length"]=>
array(1) {
[0]=>
string(3) "229"
}
["Connection"]=>
array(1) {
[0]=>
string(10) "keep-alive"
}
["Server"]=>
array(1) {
[0]=>
string(12) "nginx/1.14.1"
}
["Access-Control-Allow-Origin"]=>
array(1) {
[0]=>
string(1) "*"
}
["X-Ctxlog-Logid"]=>
array(1) {
[0]=>
string(35) "1-5d6d706e-3de0be8f72fd6342123a563e"
}
}
["headerNames":"GuzzleHttp\Psr7\Response":private]=>
array(7) {
["date"]=>
string(4) "Date"
["content-type"]=>
string(12) "Content-Type"
["content-length"]=>
string(14) "Content-Length"
["connection"]=>
string(10) "Connection"
["server"]=>
string(6) "Server"
["access-control-allow-origin"]=>
string(27) "Access-Control-Allow-Origin"
["x-ctxlog-logid"]=>
string(14) "X-Ctxlog-Logid"
}
["protocol":"GuzzleHttp\Psr7\Response":private]=>
string(3) "1.1"
["stream":"GuzzleHttp\Psr7\Response":private]=>
object(GuzzleHttp\Psr7\Stream)#353 (7) {
["stream":"GuzzleHttp\Psr7\Stream":private]=>
resource(274) of type (stream)
["size":"GuzzleHttp\Psr7\Stream":private]=>
NULL
["seekable":"GuzzleHttp\Psr7\Stream":private]=>
bool(true)
["readable":"GuzzleHttp\Psr7\Stream":private]=>
bool(true)
["writable":"GuzzleHttp\Psr7\Stream":private]=>
bool(true)
["uri":"GuzzleHttp\Psr7\Stream":private]=>
string(10) "php://temp"
["customMetadata":"GuzzleHttp\Psr7\Stream":private]=>
array(0) {
}
}
}
["twitch"]=>
object(romanzipp\Twitch\Twitch)#329 (6) {
["client":protected]=>
object(GuzzleHttp\Client)#324 (1) {
["config":"GuzzleHttp\Client":private]=>
array(8) {
["base_uri"]=>
object(GuzzleHttp\Psr7\Uri)#342 (7) {
["scheme":"GuzzleHttp\Psr7\Uri":private]=>
string(5) "https"
["userInfo":"GuzzleHttp\Psr7\Uri":private]=>
string(0) ""
["host":"GuzzleHttp\Psr7\Uri":private]=>
string(13) "api.twitch.tv"
["port":"GuzzleHttp\Psr7\Uri":private]=>
NULL
["path":"GuzzleHttp\Psr7\Uri":private]=>
string(7) "/helix/"
["query":"GuzzleHttp\Psr7\Uri":private]=>
string(0) ""
["fragment":"GuzzleHttp\Psr7\Uri":private]=>
string(0) ""
}
["handler"]=>
object(GuzzleHttp\HandlerStack)#325 (3) {
["handler":"GuzzleHttp\HandlerStack":private]=>
object(Closure)#337 (2) {
["static"]=>
array(2) {
["default"]=>
object(Closure)#335 (2) {
["static"]=>
array(2) {
["default"]=>
object(GuzzleHttp\Handler\CurlMultiHandler)#331 (5) {
["factory":"GuzzleHttp\Handler\CurlMultiHandler":private]=>
object(GuzzleHttp\Handler\CurlFactory)#332 (2) {
["handles":"GuzzleHttp\Handler\CurlFactory":private]=>
array(0) {
}
["maxHandles":"GuzzleHttp\Handler\CurlFactory":private]=>
int(50)
}
["selectTimeout":"GuzzleHttp\Handler\CurlMultiHandler":private]=>
int(1)
["active":"GuzzleHttp\Handler\CurlMultiHandler":private]=>
NULL
["handles":"GuzzleHttp\Handler\CurlMultiHandler":private]=>
array(0) {
}
["delays":"GuzzleHttp\Handler\CurlMultiHandler":private]=>
array(0) {
}
}
["sync"]=>
object(GuzzleHttp\Handler\CurlHandler)#333 (1) {
["factory":"GuzzleHttp\Handler\CurlHandler":private]=>
object(GuzzleHttp\Handler\CurlFactory)#334 (2) {
["handles":"GuzzleHttp\Handler\CurlFactory":private]=>
array(1) {
[0]=>
resource(276) of type (curl)
}
["maxHandles":"GuzzleHttp\Handler\CurlFactory":private]=>
int(3)
}
}
}
["parameter"]=>
array(2) {
["$request"]=>
string(10) "<required>"
["$options"]=>
string(10) "<required>"
}
}
["streaming"]=>
object(GuzzleHttp\Handler\StreamHandler)#336 (1) {
["lastHeaders":"GuzzleHttp\Handler\StreamHandler":private]=>
array(0) {
}
}
}
["parameter"]=>
array(2) {
["$request"]=>
string(10) "<required>"
["$options"]=>
string(10) "<required>"
}
}
["stack":"GuzzleHttp\HandlerStack":private]=>
array(4) {
[0]=>
array(2) {
[0]=>
object(Closure)#338 (1) {
["parameter"]=>
array(1) {
["$handler"]=>
string(10) "<required>"
}
}
[1]=>
string(11) "http_errors"
}
[1]=>
array(2) {
[0]=>
object(Closure)#339 (1) {
["parameter"]=>
array(1) {
["$handler"]=>
string(10) "<required>"
}
}
[1]=>
string(15) "allow_redirects"
}
[2]=>
array(2) {
[0]=>
object(Closure)#340 (1) {
["parameter"]=>
array(1) {
["$handler"]=>
string(10) "<required>"
}
}
[1]=>
string(7) "cookies"
}
[3]=>
array(2) {
[0]=>
object(Closure)#341 (1) {
["parameter"]=>
array(1) {
["$handler"]=>
string(10) "<required>"
}
}
[1]=>
string(12) "prepare_body"
}
}
["cached":"GuzzleHttp\HandlerStack":private]=>
object(Closure)#351 (2) {
["static"]=>
array(1) {
["handler"]=>
object(GuzzleHttp\RedirectMiddleware)#350 (1) {
["nextHandler":"GuzzleHttp\RedirectMiddleware":private]=>
object(Closure)#349 (2) {
["static"]=>
array(1) {
["handler"]=>
object(GuzzleHttp\PrepareBodyMiddleware)#346 (1) {
["nextHandler":"GuzzleHttp\PrepareBodyMiddleware":private]=>
object(Closure)#337 (2) {
["static"]=>
array(2) {
["default"]=>
object(Closure)#335 (2) {
["static"]=>
array(2) {
["default"]=>
object(GuzzleHttp\Handler\CurlMultiHandler)#331 (5) {
["factory":"GuzzleHttp\Handler\CurlMultiHandler":private]=>
object(GuzzleHttp\Handler\CurlFactory)#332 (2) {
["handles":"GuzzleHttp\Handler\CurlFactory":private]=>
array(0) {
}
["maxHandles":"GuzzleHttp\Handler\CurlFactory":private]=>
int(50)
}
["selectTimeout":"GuzzleHttp\Handler\CurlMultiHandler":private]=>
int(1)
["active":"GuzzleHttp\Handler\CurlMultiHandler":private]=>
NULL
["handles":"GuzzleHttp\Handler\CurlMultiHandler":private]=>
array(0) {
}
["delays":"GuzzleHttp\Handler\CurlMultiHandler":private]=>
array(0) {
}
}
["sync"]=>
object(GuzzleHttp\Handler\CurlHandler)#333 (1) {
["factory":"GuzzleHttp\Handler\CurlHandler":private]=>
object(GuzzleHttp\Handler\CurlFactory)#334 (2) {
["handles":"GuzzleHttp\Handler\CurlFactory":private]=>
array(1) {
[0]=>
resource(276) of type (curl)
}
["maxHandles":"GuzzleHttp\Handler\CurlFactory":private]=>
int(3)
}
}
}
["parameter"]=>
array(2) {
["$request"]=>
string(10) "<required>"
["$options"]=>
string(10) "<required>"
}
}
["streaming"]=>
object(GuzzleHttp\Handler\StreamHandler)#336 (1) {
["lastHeaders":"GuzzleHttp\Handler\StreamHandler":private]=>
array(0) {
}
}
}
["parameter"]=>
array(2) {
["$request"]=>
string(10) "<required>"
["$options"]=>
string(10) "<required>"
}
}
}
}
["parameter"]=>
array(2) {
["$request"]=>
string(10) "<required>"
["$options"]=>
string(10) "<required>"
}
}
}
}
["parameter"]=>
array(2) {
["$request"]=>
string(10) "<required>"
["$options"]=>
string(10) "<required>"
}
}
}
["allow_redirects"]=>
array(5) {
["max"]=>
int(5)
["protocols"]=>
array(2) {
[0]=>
string(4) "http"
[1]=>
string(5) "https"
}
["strict"]=>
bool(false)
["referer"]=>
bool(false)
["track_redirects"]=>
bool(false)
}
["http_errors"]=>
bool(true)
["decode_content"]=>
bool(true)
["verify"]=>
bool(true)
["cookies"]=>
bool(false)
["headers"]=>
array(1) {
["User-Agent"]=>
string(38) "GuzzleHttp/6.3.3 curl/7.52.1 PHP/7.2.8"
}
}
}
["paginator":protected]=>
NULL
["token":protected]=>
NULL
["clientId":protected]=>
string(30) "REDACTED"
["clientSecret":protected]=>
string(30) "REDACTED"
["redirectUri":protected]=>
string(43) "REDACTED"
}
}
With #77, everything works fine when I test with Twitch CLI, but in production I have the error:
Unable to extract timestamp and signatures from header
Because the Timestamp is not the same between Twitch CLI and the real Twitch call:
CLI: Twitch-Eventsub-Message-Timestamp: 2021-04-11T09:40:55.902801Z
Twitch: Twitch-Eventsub-Message-Timestamp: 2021-04-11T09:49:55.813Z
I've updated TIMESTAMP_PATTERN
but i'm not sure if it's correct:
const TIMESTAMP_PATTERN = '/^(?<pre>[\d\-:.T]+)\.(?<nano>\d{3,9})Z$/';
composer.json
- "minimum-stability": "dev",
Hi, use the last version of Laravel Twitch:
$twitch->unsubscribeWebhook(
"https://***/twitch/callback/7",
$twitch->webhookTopicStreamMonitor(190203376)
);
After execute I've got a {"error":"Bad Request","status":400,"message":"hub.topic unsupported topic"}
Looked at params in request and saw:
hub.topic=https%253A%252F%252Fapi.twitch.tv%252Fhelix%252Fstreams%253Fuser_id%253D190203376
%253A%252F%252F
It's not the same as %3A%2F%2F
as it get after urlencode()
Could you fix it?
BTW: use
"name": "guzzlehttp/guzzle",
"version": "6.3.3",
EventSub replaced the Webhooks system.
The endpoints in the /webhooks namespace are no longer available.
It may be good, to remove them from the lib.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.