Skip to content

Commit ce0b6e6

Browse files
authored
Merge pull request #22 from ChessCom/master
Add initial Helix support
2 parents db405e0 + 01e24a3 commit ce0b6e6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+2421
-6
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ composer-test.lock
55
vendor/
66
.idea
77
.DS_STORE
8+
.php_cs.cache

.php_cs.dist

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
$finder = PhpCsFixer\Finder::create()
4+
->in('src/NewTwitchApi/')
5+
;
6+
7+
return PhpCsFixer\Config::create()
8+
->setFinder($finder)
9+
;

.travis.yml

-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
language: php
22
php:
3-
- '5.6'
4-
- '7.0'
53
- '7.1'
64
- '7.2'
75

README.md

+146-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,151 @@
11
# twitch-api-php
22

3-
A Twitch Kraken API client for PHP.
3+
# New Twitch API (Helix)
4+
5+
A New Twitch API (Helix) client for PHP. The code for the new API is all contained within `src/NewApi/`. This is because the New API code is meant to be separate from the old Kraken API code, such that in the future, when Kraken is no longer available, the old Kraken code can be removed without affecting the new API code. Additionally, keeping them separate allows for existing code using the Kraken part of this library to continue to function, untouched by the new code.
6+
7+
The New Twitch API client is still being developed and is currently incomplete. The endpoints that are implemented are usable, but not all endpoints have been implemented yet. If an endpoint you need is missing, incomplete, or not working correctly, please report it or fix it if you can and create a PR for it.
8+
9+
## Usage
10+
11+
Everything stems from the `NewTwitchApi` class. However, if you want to individually instantiate `UsersApi`, `OauthApi`, etc. you are free to do so.
12+
13+
The API calls generally return an object implementing `ResponseInterface`. Since you are getting the full `Response` object, you'll need to handle its contents, e.g. by decoding then into an object with `json_decode()`. This library does not assume this is what you want to do, so it does not do this for you automatically. This library simply acts as a middleman between your code and Twitch, providing you with the raw responses the Twitch API returns.
14+
15+
The individual API classes that can be called from `NewTwitchApi` correspond to the [New Twitch API documentation](https://dev.twitch.tv/docs/api/). `OauthApi` is for Oauth calls. `WebhooksSubscriptionApi` is for subscribing/unsubscribing to webhooks. The rest of the API classes are based on the resources listed [here](https://dev.twitch.tv/docs/api/reference/). The methods in the classes generally correspond to the endpoints for each resource. The naming convention was chosen to try and match the Twitch documentation. Each primary endpoint method (not convenience or helper methods) should have an `@link` annotation with a URL to that endpoint's specific documentation.
16+
17+
## Examples
18+
19+
Getting a user's information via their access token:
20+
21+
```php
22+
// Assuming you already have the access token.
23+
$accessToken = 'the token';
24+
25+
// The Guzzle client used can be the included `HelixGuzzleClient` class, for convenience.
26+
// You can also use a mock, fake, or other double for testing, of course.
27+
$helixGuzzleClient = new HelixGuzzleClient();
28+
29+
// Instantiate NewTwitchApi. Can be done in a service layer and injected as well.
30+
$newTwitchApi = new NewTwitchApi($helixGuzzleClient, $clientId, $clientSecret);
31+
32+
try {
33+
// Make the API call. A ResponseInterface object is returned.
34+
$response = $newTwitchApi->getUsersApi()->getUserByAccessToken($accessToken);
35+
} (catch GuzzleException $e) {
36+
// Handle error appropriately for your application
37+
}
38+
39+
// Get and decode the actual content sent by Twitch.
40+
$responseContent = json_decode($response->getBody()->getContents());
41+
42+
// Return the first (or only) user.
43+
return $responseContent->data[0];
44+
```
45+
46+
### CLI Test Client
47+
48+
In order to make testing the New Twitch API code easier, there is an interactive CLI script that can be run. This is found at `bin/new-api-cli-test-client.php`.
49+
50+
To run it, execute `./bin/new-api-cli-test-client.php <client-id> <client-secret>`, passing in your client ID and secret, respectively. The script will interactively walk you through the rest. You'll be prompted for which API endpoint you'd like to call. Then, you'll be prompted for any parameters that are available for that call. After the API call is made, you're presented with the URI of the request followed by the body of the response.
51+
52+
Here's an example of the CLI client in action, getting the game information for Minecraft and then validating an invalid access token.
53+
54+
```bash
55+
$ ./bin/new-api-cli-test-client.php REDACTED_CLIENT_ID REDACTED_CLIENT_SECRET
56+
Twitch API Testing Tool
57+
58+
Which endpoint would you like to call?
59+
0) Quit
60+
1) Validate an Access Token
61+
2) Refresh an Access Token
62+
3) Get Games
63+
4) Get Streams
64+
5) Get Users
65+
6) Get Users Follows
66+
Choice: 3
67+
68+
Get Games
69+
IDs (separated by commas):
70+
Names (separated by commas): Minecraft
71+
72+
games?name=Minecraft
73+
74+
{
75+
"data": [
76+
{
77+
"id": "27471",
78+
"name": "Minecraft",
79+
"box_art_url": "https:\/\/static-cdn.jtvnw.net\/ttv-boxart\/Minecraft-{width}x{height}.jpg"
80+
}
81+
]
82+
}
83+
84+
Which endpoint would you like to call?
85+
0) Quit
86+
1) Validate an Access Token
87+
2) Refresh an Access Token
88+
3) Get Games
89+
4) Get Streams
90+
5) Get Users
91+
6) Get Users Follows
92+
Choice: 1
93+
94+
Validate an Access Token
95+
Access token: foobar
96+
97+
/oauth2/validate
98+
99+
{
100+
"status": 401,
101+
"message": "invalid access token"
102+
}
103+
104+
Which endpoint would you like to call?
105+
0) Quit
106+
1) Validate an Access Token
107+
2) Refresh an Access Token
108+
3) Get Games
109+
4) Get Streams
110+
5) Get Users
111+
6) Get Users Follows
112+
Choice: 0
113+
114+
Quit
115+
$
116+
```
117+
118+
## Developer Tools
119+
120+
### PHP Coding Standards Fixer
121+
122+
[PHP Coding Standards Fixer](https://cs.sensiolabs.org/) (`php-cs-fixer`) has been added, specifically for the New Twitch API code. A configuration file for it can be found in `.php_cs.dist`. The ruleset is left at default (PSR-2 at this time). The configuration file mostly just limits it's scope to only the New Twitch API code.
123+
124+
You can run the fixer with `vendor/bin/php-cs-fixer fix`. However, the easiest way to run the fixer is with the provided git hook.
125+
126+
### Git pre-commit Hook
127+
128+
In `bin/git/hooks`, you'll find a `pre-commit` hook that you can add to git that will automatically run the `php-cs-fixer` everytime you commit. The result is that, after the commit is made, any changes that fixer has made are left as unstaged changes. You can review them, then add and commit them.
129+
130+
To install the hook, go to `.git/hooks` and `ln -s ../../bin/git/hooks/pre-commit`.
131+
132+
## API Documentation
133+
134+
The New Twitch API docs can be found [here](https://dev.twitch.tv/docs/api/).
135+
136+
## License
137+
138+
Distributed under the [MIT](LICENSE) license.
139+
140+
---
141+
---
142+
---
143+
144+
# Kraken
145+
146+
A Twitch Kraken API client for PHP. This is the old API, which is deprecated and will be deleted soon. Please use Helix instead. If something is missing from the Helix API, please add it or request it.
147+
148+
The documentation below is left for legacy purposes, until Kraken support is removed.
4149

5150
[![Build Status](https://travis-ci.org/nicklaw5/twitch-api-php.svg?branch=master)](https://travis-ci.org/nicklaw5/twitch-api-php)
6151

bin/git/hooks/pre-commit

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/usr/bin/env sh
2+
./vendor/bin/php-cs-fixer fix

bin/new-api-cli-test-client.php

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/usr/bin/env php
2+
<?php
3+
4+
require __DIR__ . '/../vendor/autoload.php';
5+
6+
use NewTwitchApi\Cli\CliClient;
7+
8+
try {
9+
(new CliClient($argv))->run();
10+
} catch (InvalidArgumentException $e) {
11+
echo $e->getMessage();
12+
}

composer.json

+7-3
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,24 @@
1212
}
1313
],
1414
"require": {
15-
"php": ">=5.6.0",
15+
"php": ">=7.1.0",
16+
"ext-json": "*",
1617
"guzzlehttp/guzzle": "~6.0"
1718
},
1819
"require-dev": {
20+
"friendsofphp/php-cs-fixer": "^2.13",
21+
"phpspec/phpspec": "^5.1",
1922
"phpunit/phpunit": "^5.7"
2023
},
2124
"autoload": {
2225
"psr-4": {
23-
"TwitchApi\\": "src/"
26+
"TwitchApi\\": "src/",
27+
"NewTwitchApi\\": "src/NewTwitchApi"
2428
}
2529
},
2630
"autoload-dev": {
2731
"psr-4": {
28-
"TwitchApi\\Tests\\": "test/"
32+
"Tests\\": "test/"
2933
}
3034
}
3135
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
namespace spec\NewTwitchApi\Auth;
4+
5+
use GuzzleHttp\Psr7\Uri;
6+
use PhpSpec\ObjectBehavior;
7+
8+
class AuthGuzzleClientSpec extends ObjectBehavior
9+
{
10+
function it_should_have_correct_base_uri()
11+
{
12+
/** @var Uri $uri */
13+
$uri = $this->getConfig('base_uri');
14+
$uri->getScheme()->shouldBe('https');
15+
$uri->getHost()->shouldBe('id.twitch.tv');
16+
$uri->getPath()->shouldBe('/oauth2/');
17+
}
18+
19+
function it_should_have_passed_in_config_params_instead_of_defaults()
20+
{
21+
$this->beConstructedWith(['base_uri' => 'https://different.url']);
22+
$this->getConfig('base_uri')->getHost()->shouldBe('different.url');
23+
}
24+
}
+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
<?php
2+
3+
namespace spec\NewTwitchApi\Auth;
4+
5+
use GuzzleHttp\Client;
6+
use GuzzleHttp\Psr7\Request;
7+
use GuzzleHttp\Psr7\Response;
8+
use PhpSpec\ObjectBehavior;
9+
10+
class OauthApiSpec extends ObjectBehavior
11+
{
12+
function let(Client $guzzleClient)
13+
{
14+
$this->beConstructedWith('client-id', 'client-secret', $guzzleClient);
15+
}
16+
17+
function it_should_get_auth_url(Client $guzzleClient)
18+
{
19+
$guzzleClient->getConfig('base_uri')->willReturn('https://id.twitch.tv/oauth2/');
20+
$this->getAuthUrl('https://redirect.url')->shouldReturn(
21+
'https://id.twitch.tv/oauth2/authorize?client_id=client-id&redirect_uri=https://redirect.url&response_type=code&scope='
22+
);
23+
}
24+
25+
function it_should_get_access_token(Client $guzzleClient, Response $response)
26+
{
27+
$request = new Request(
28+
'POST',
29+
'token'
30+
);
31+
$guzzleClient->send($request, ['json' => [
32+
'client_id' => 'client-id',
33+
'client_secret' => 'client-secret',
34+
'grant_type' => 'authorization_code',
35+
'redirect_uri' => 'https://redirect.url',
36+
'code' => 'user-code-from-twitch',
37+
'state' => null,
38+
]])->willReturn($response);
39+
40+
$this->getUserAccessToken('user-code-from-twitch', 'https://redirect.url')->shouldBe($response);
41+
}
42+
43+
function it_should_get_refresh_token(Client $guzzleClient, Response $response)
44+
{
45+
$request = new Request(
46+
'POST',
47+
'token'
48+
);
49+
$guzzleClient->send($request, ['json' => [
50+
'client_id' => 'client-id',
51+
'client_secret' => 'client-secret',
52+
'grant_type' => 'refresh_token',
53+
'refresh_token' => 'user-refresh-token',
54+
]])->willReturn($response);
55+
56+
$this->refreshToken('user-refresh-token')->shouldBe($response);
57+
}
58+
59+
function it_should_validate_access_token(Client $guzzleClient, Response $response)
60+
{
61+
$request = new Request(
62+
'GET',
63+
'validate',
64+
[
65+
'Authorization' => 'OAuth user-access-token',
66+
]
67+
);
68+
$guzzleClient->send($request, [])->willReturn($response);
69+
70+
$this->validateAccessToken('user-access-token')->shouldBe($response);
71+
}
72+
73+
function it_should_return_true_if_access_token_is_valid(Client $guzzleClient, Response $response)
74+
{
75+
$request = new Request(
76+
'GET',
77+
'validate',
78+
[
79+
'Authorization' => 'OAuth user-access-token',
80+
]
81+
);
82+
$response->getStatusCode()->willReturn(200);
83+
$guzzleClient->send($request, [])->willReturn($response);
84+
85+
$this->isValidAccessToken('user-access-token')->shouldReturn(true);
86+
}
87+
88+
function it_should_return_false_if_access_token_is_invalid(Client $guzzleClient, Response $response)
89+
{
90+
$request = new Request(
91+
'GET',
92+
'validate',
93+
[
94+
'Authorization' => 'OAuth invalid-user-access-token',
95+
]
96+
);
97+
$response->getStatusCode()->willReturn(401);
98+
$guzzleClient->send($request, [])->willReturn($response);
99+
100+
$this->isValidAccessToken('invalid-user-access-token')->shouldReturn(false);
101+
}
102+
103+
function it_should_get_app_access_token(Client $guzzleClient, Response $response)
104+
{
105+
$request = new Request(
106+
'POST',
107+
'token'
108+
);
109+
$guzzleClient->send($request, ['json' => [
110+
'client_id' => 'client-id',
111+
'client_secret' => 'client-secret',
112+
'grant_type' => 'client_credentials',
113+
'scope' => '',
114+
]])->willReturn($response);
115+
116+
$this->getAppAccessToken()->shouldBe($response);
117+
}
118+
}
+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
namespace spec\NewTwitchApi\Cli;
4+
5+
use InvalidArgumentException;
6+
use NewTwitchApi\Cli\CliClient;
7+
use PhpSpec\ObjectBehavior;
8+
9+
class CliClientSpec extends ObjectBehavior
10+
{
11+
function it_is_initializable()
12+
{
13+
$this->beConstructedWith(['cmd', 'client-id', 'client-secret']);
14+
$this->shouldHaveType(CliClient::class);
15+
$this->shouldNotThrow(InvalidArgumentException::class)->duringInstantiation();
16+
}
17+
18+
function it_throws_an_exception_without_client_id()
19+
{
20+
$this->beConstructedWith(['cmd']);
21+
$this->shouldThrow(InvalidArgumentException::class)->duringInstantiation();
22+
}
23+
24+
function it_throws_an_exception_without_client_secret()
25+
{
26+
$this->beConstructedWith(['cmd', 'client-id']);
27+
$this->shouldThrow(InvalidArgumentException::class)->duringInstantiation();
28+
}
29+
}

0 commit comments

Comments
 (0)