diff --git a/spec/TwitchApi/Resources/ChannelsApiSpec.php b/spec/TwitchApi/Resources/ChannelsApiSpec.php index d99245b..969d1ae 100644 --- a/spec/TwitchApi/Resources/ChannelsApiSpec.php +++ b/spec/TwitchApi/Resources/ChannelsApiSpec.php @@ -57,4 +57,28 @@ function it_should_modify_channel_with_opts(RequestGenerator $requestGenerator, $requestGenerator->generate('PATCH', 'channels', 'TEST_TOKEN', [['key' => 'broadcaster_id', 'value' => '123']], [['key' => 'game_id', 'value' => '0'], ['key' => 'broadcaster_language', 'value' => 'en'], ['key' => 'title', 'value' => 'test 123'], ['key' => 'delay', 'value' => 5]])->willReturn($request); $this->modifyChannelInfo('TEST_TOKEN', '123', ['game_id' => '0', 'broadcaster_language' => 'en', 'title' => 'test 123', 'delay' => 5])->shouldBe($response); } + + function it_should_get_followed_channels(RequestGenerator $requestGenerator, Request $request, Response $response) + { + $requestGenerator->generate('GET', 'channels/followed', 'TEST_TOKEN', [['key' => 'user_id', 'value' => '123']], [])->willReturn($request); + $this->getFollowedChannels('TEST_TOKEN', '123')->shouldBe($response); + } + + function it_should_get_followed_channels_with_opts(RequestGenerator $requestGenerator, Request $request, Response $response) + { + $requestGenerator->generate('GET', 'channels/followed', 'TEST_TOKEN', [['key' => 'user_id', 'value' => '123'], ['key' => 'broadcaster_id', 'value' => '456'], ['key' => 'first', 'value' => 100], ['key' => 'after', 'value' => 'abc']], [])->willReturn($request); + $this->getFollowedChannels('TEST_TOKEN', '123', '456', 100, 'abc')->shouldBe($response); + } + + function it_should_get_channel_followers(RequestGenerator $requestGenerator, Request $request, Response $response) + { + $requestGenerator->generate('GET', 'channels/followers', 'TEST_TOKEN', [['key' => 'broadcaster_id', 'value' => '123']], [])->willReturn($request); + $this->getChannelFollowers('TEST_TOKEN', '123')->shouldBe($response); + } + + function it_should_get_channel_followers_with_opts(RequestGenerator $requestGenerator, Request $request, Response $response) + { + $requestGenerator->generate('GET', 'channels/followers', 'TEST_TOKEN', [['key' => 'broadcaster_id', 'value' => '123'], ['key' => 'user_id', 'value' => '456'], ['key' => 'first', 'value' => 100], ['key' => 'after', 'value' => 'abc']], [])->willReturn($request); + $this->getChannelFollowers('TEST_TOKEN', '123', '456', 100, 'abc')->shouldBe($response); + } } diff --git a/spec/TwitchApi/Resources/ChatApiSpec.php b/spec/TwitchApi/Resources/ChatApiSpec.php index 8f63576..9b925e3 100644 --- a/spec/TwitchApi/Resources/ChatApiSpec.php +++ b/spec/TwitchApi/Resources/ChatApiSpec.php @@ -117,4 +117,10 @@ function it_should_get_chatters_with_opts(RequestGenerator $requestGenerator, Re $requestGenerator->generate('GET', 'chat/chatters', 'TEST_TOKEN', [['key' => 'broadcaster_id', 'value' => '123'], ['key' => 'moderator_id', 'value' => '456'],['key' => 'first', 'value' => 100], ['key' => 'after', 'value' => 'abc']], [])->willReturn($request); $this->getChatters('TEST_TOKEN', '123', '456', 100, 'abc')->shouldBe($response); } + + function it_should_send_a_shoutout(RequestGenerator $requestGenerator, Request $request, Response $response) + { + $requestGenerator->generate('POST', 'chat/shoutouts', 'TEST_TOKEN', [['key' => 'from_broadcaster_id', 'value' => '123'], ['key' => 'to_broadcaster_id', 'value' => '456'], ['key' => 'moderator_id', 'value' => '789']], [])->willReturn($request); + $this->sendShoutout('TEST_TOKEN', '123', '456', '789')->shouldBe($response); + } } diff --git a/spec/TwitchApi/Resources/EventSubApiSpec.php b/spec/TwitchApi/Resources/EventSubApiSpec.php index a3b9c5a..9b13d0f 100644 --- a/spec/TwitchApi/Resources/EventSubApiSpec.php +++ b/spec/TwitchApi/Resources/EventSubApiSpec.php @@ -87,8 +87,8 @@ function it_should_subscribe_to_channel_update(RequestGenerator $requestGenerato function it_should_subscribe_to_channel_follow(RequestGenerator $requestGenerator, Request $request, Response $response) { - $this->createEventSubSubscription('channel.follow', '1', ['broadcaster_user_id' => '12345'], $requestGenerator)->willReturn($request); - $this->subscribeToChannelFollow($this->bearer, $this->secret, $this->callback, '12345')->shouldBe($response); + $this->createEventSubSubscription('channel.follow', '2', ['broadcaster_user_id' => '12345', 'moderator_user_id' => '54321'], $requestGenerator)->willReturn($request); + $this->subscribeToChannelFollow($this->bearer, $this->secret, $this->callback, '12345', '54321')->shouldBe($response); } function it_should_subscribe_to_channel_subscribe(RequestGenerator $requestGenerator, Request $request, Response $response) @@ -309,37 +309,49 @@ function it_should_subscribe_to_drop_entitelement_grant_with_opts(RequestGenerat function it_should_subscribe_to_channel_charity_campaign_start(RequestGenerator $requestGenerator, Request $request, Response $response) { - $this->createEventSubSubscription('channel.charity_campaign.start', 'beta', ['broadcaster_user_id' => '12345'], $requestGenerator)->willReturn($request); + $this->createEventSubSubscription('channel.charity_campaign.start', '1', ['broadcaster_user_id' => '12345'], $requestGenerator)->willReturn($request); $this->subscribeToChannelCharityCampaignStart($this->bearer, $this->secret, $this->callback, '12345')->shouldBe($response); } function it_should_subscribe_to_channel_charity_campaign_progress(RequestGenerator $requestGenerator, Request $request, Response $response) { - $this->createEventSubSubscription('channel.charity_campaign.progress', 'beta', ['broadcaster_user_id' => '12345'], $requestGenerator)->willReturn($request); + $this->createEventSubSubscription('channel.charity_campaign.progress', '1', ['broadcaster_user_id' => '12345'], $requestGenerator)->willReturn($request); $this->subscribeToChannelCharityCampaignProgress($this->bearer, $this->secret, $this->callback, '12345')->shouldBe($response); } function it_should_subscribe_to_channel_charity_campaign_stop(RequestGenerator $requestGenerator, Request $request, Response $response) { - $this->createEventSubSubscription('channel.charity_campaign.stop', 'beta', ['broadcaster_user_id' => '12345'], $requestGenerator)->willReturn($request); + $this->createEventSubSubscription('channel.charity_campaign.stop', '1', ['broadcaster_user_id' => '12345'], $requestGenerator)->willReturn($request); $this->subscribeToChannelCharityCampaignStop($this->bearer, $this->secret, $this->callback, '12345')->shouldBe($response); } function it_should_subscribe_to_channel_charity_campaign_donate(RequestGenerator $requestGenerator, Request $request, Response $response) { - $this->createEventSubSubscription('channel.charity_campaign.donate', 'beta', ['broadcaster_user_id' => '12345'], $requestGenerator)->willReturn($request); + $this->createEventSubSubscription('channel.charity_campaign.donate', '1', ['broadcaster_user_id' => '12345'], $requestGenerator)->willReturn($request); $this->subscribeToChannelCharityCampaignDonate($this->bearer, $this->secret, $this->callback, '12345')->shouldBe($response); } function it_should_subscribe_to_channel_shield_mode_begin(RequestGenerator $requestGenerator, Request $request, Response $response) { - $this->createEventSubSubscription('channel.shield_mode.begin', 'beta', ['broadcaster_user_id' => '12345', 'moderator_user_id' => '54321'], $requestGenerator)->willReturn($request); + $this->createEventSubSubscription('channel.shield_mode.begin', '1', ['broadcaster_user_id' => '12345', 'moderator_user_id' => '54321'], $requestGenerator)->willReturn($request); $this->subscribeToChannelShieldModeBegin($this->bearer, $this->secret, $this->callback, '12345', '54321')->shouldBe($response); } function it_should_subscribe_to_channel_shield_mode_end(RequestGenerator $requestGenerator, Request $request, Response $response) { - $this->createEventSubSubscription('channel.shield_mode.end', 'beta', ['broadcaster_user_id' => '12345', 'moderator_user_id' => '54321'], $requestGenerator)->willReturn($request); + $this->createEventSubSubscription('channel.shield_mode.end', '1', ['broadcaster_user_id' => '12345', 'moderator_user_id' => '54321'], $requestGenerator)->willReturn($request); $this->subscribeToChannelShieldModeEnd($this->bearer, $this->secret, $this->callback, '12345', '54321')->shouldBe($response); } + + function it_should_subscribe_to_channel_shoutout_create(RequestGenerator $requestGenerator, Request $request, Response $response) + { + $this->createEventSubSubscription('channel.shoutout.create', '1', ['broadcaster_user_id' => '12345', 'moderator_user_id' => '54321'], $requestGenerator)->willReturn($request); + $this->subscribeToChannelShoutoutCreate($this->bearer, $this->secret, $this->callback, '12345', '54321')->shouldBe($response); + } + + function it_should_subscribe_to_channel_shoutout_receive(RequestGenerator $requestGenerator, Request $request, Response $response) + { + $this->createEventSubSubscription('channel.shoutout.receive', '1', ['broadcaster_user_id' => '12345', 'moderator_user_id' => '54321'], $requestGenerator)->willReturn($request); + $this->subscribeToChannelShoutoutReceive($this->bearer, $this->secret, $this->callback, '12345', '54321')->shouldBe($response); + } } diff --git a/spec/TwitchApi/Resources/GoalsApiSpec.php b/spec/TwitchApi/Resources/GoalsApiSpec.php index 0f62ebf..e221c6d 100644 --- a/spec/TwitchApi/Resources/GoalsApiSpec.php +++ b/spec/TwitchApi/Resources/GoalsApiSpec.php @@ -19,7 +19,7 @@ function let(HelixGuzzleClient $guzzleClient, RequestGenerator $requestGenerator function it_should_get_goals_by_broadcaster_id(RequestGenerator $requestGenerator, Request $request, Response $response) { $requestGenerator->generate('GET', 'goals', 'TEST_TOKEN', [['key' => 'broadcaster_id', 'value' => '123']], [])->willReturn($request); - $this->getGoals('TEST_TOKEN', ['123'])->shouldBe($response); + $this->getGoals('TEST_TOKEN', '123')->shouldBe($response); } } diff --git a/src/Resources/ChannelsApi.php b/src/Resources/ChannelsApi.php index 323d590..4daa3b8 100644 --- a/src/Resources/ChannelsApi.php +++ b/src/Resources/ChannelsApi.php @@ -52,4 +52,54 @@ public function modifyChannelInfo(string $bearer, string $broadcasterId, $bodyPa return $this->patchApi('channels', $bearer, $queryParamsMap, $bodyParamsMap); } + + /** + * @throws GuzzleException + * @link https://dev.twitch.tv/docs/api/reference/#get-followed-channels + */ + public function getFollowedChannels(string $bearer, string $userId, string $broadcasterId = null, int $first = null, string $after = null): ResponseInterface + { + $queryParamsMap = []; + + $queryParamsMap[] = ['key' => 'user_id', 'value' => $userId]; + + if ($broadcasterId) { + $queryParamsMap[] = ['key' => 'broadcaster_id', 'value' => $broadcasterId]; + } + + if ($first) { + $queryParamsMap[] = ['key' => 'first', 'value' => $first]; + } + + if ($after) { + $queryParamsMap[] = ['key' => 'after', 'value' => $after]; + } + + return $this->getApi('channels/followed', $bearer, $queryParamsMap); + } + + /** + * @throws GuzzleException + * @link https://dev.twitch.tv/docs/api/reference/#get-channel-followers + */ + public function getChannelFollowers(string $bearer, string $broadcasterId, string $userId = null, int $first = null, string $after = null): ResponseInterface + { + $queryParamsMap = []; + + $queryParamsMap[] = ['key' => 'broadcaster_id', 'value' => $broadcasterId]; + + if ($userId) { + $queryParamsMap[] = ['key' => 'user_id', 'value' => $userId]; + } + + if ($first) { + $queryParamsMap[] = ['key' => 'first', 'value' => $first]; + } + + if ($after) { + $queryParamsMap[] = ['key' => 'after', 'value' => $after]; + } + + return $this->getApi('channels/followers', $bearer, $queryParamsMap); + } } diff --git a/src/Resources/ChatApi.php b/src/Resources/ChatApi.php index 8f322fe..1786c64 100644 --- a/src/Resources/ChatApi.php +++ b/src/Resources/ChatApi.php @@ -179,4 +179,21 @@ public function getChatters(string $bearer, string $broadcasterId, string $moder return $this->getApi('chat/chatters', $bearer, $queryParamsMap); } + + /** + * @throws GuzzleException + * @link https://dev.twitch.tv/docs/api/reference/#send-a-shoutout + */ + public function sendShoutout(string $bearer, string $fromBroadcasterId, string $toBroadcasterId, string $moderatorId): ResponseInterface + { + $queryParamsMap = []; + + $queryParamsMap[] = ['key' => 'from_broadcaster_id', 'value' => $fromBroadcasterId]; + + $queryParamsMap[] = ['key' => 'to_broadcaster_id', 'value' => $toBroadcasterId]; + + $queryParamsMap[] = ['key' => 'moderator_id', 'value' => $moderatorId]; + + return $this->postApi('chat/shoutouts', $bearer, $queryParamsMap); + } } diff --git a/src/Resources/EventSubApi.php b/src/Resources/EventSubApi.php index a1faae0..1ce3877 100644 --- a/src/Resources/EventSubApi.php +++ b/src/Resources/EventSubApi.php @@ -91,17 +91,20 @@ public function subscribeToChannelUpdate(string $bearer, string $secret, string } /** - * @link https://dev.twitch.tv/docs/eventsub/eventsub-subscription-types#channelfollow + * @link https://dev.twitch.tv/docs/eventsub/eventsub-subscription-types/#channelfollow */ - public function subscribeToChannelFollow(string $bearer, string $secret, string $callback, string $twitchId): ResponseInterface + public function subscribeToChannelFollow(string $bearer, string $secret, string $callback, string $twitchId, string $moderatorId): ResponseInterface { return $this->createEventSubSubscription( $bearer, $secret, $callback, 'channel.follow', - '1', - ['broadcaster_user_id' => $twitchId], + '2', + [ + 'broadcaster_user_id' => $twitchId, + 'moderator_user_id' => $moderatorId, + ], ); } @@ -495,6 +498,22 @@ public function subscribeToChannelShieldModeEnd(string $bearer, string $secret, return $this->subscribeToChannelShieldMode($bearer, $secret, $callback, $twitchId, $moderatorId, 'end'); } + /** + * @link https://dev.twitch.tv/docs/eventsub/eventsub-subscription-types/#channelshoutoutcreate + */ + public function subscribeToChannelShoutoutCreate(string $bearer, string $secret, string $callback, string $twitchId, string $moderatorId): ResponseInterface + { + return $this->subscribeToChannelShoutout($bearer, $secret, $callback, $twitchId, $moderatorId, 'create'); + } + + /** + * @link https://dev.twitch.tv/docs/eventsub/eventsub-subscription-types/#channelshoutoutreceive + */ + public function subscribeToChannelShoutoutReceive(string $bearer, string $secret, string $callback, string $twitchId, string $moderatorId): ResponseInterface + { + return $this->subscribeToChannelShoutout($bearer, $secret, $callback, $twitchId, $moderatorId, 'receive'); + } + /** * @link https://dev.twitch.tv/docs/eventsub/eventsub-subscription-types/#dropentitlementgrant */ @@ -661,7 +680,7 @@ private function subscribeToChannelCharityCampaign(string $bearer, string $secre $secret, $callback, sprintf('channel.charity_campaign.%s', $eventType), - 'beta', + '1', ['broadcaster_user_id' => $twitchId], ); } @@ -673,7 +692,22 @@ private function subscribeToChannelShieldMode(string $bearer, string $secret, st $secret, $callback, sprintf('channel.shield_mode.%s', $eventType), - 'beta', + '1', + [ + 'broadcaster_user_id' => $twitchId, + 'moderator_user_id' => $moderatorId, + ], + ); + } + + private function subscribeToChannelShoutout(string $bearer, string $secret, string $callback, string $twitchId, string $moderatorId, string $eventType): ResponseInterface + { + return $this->createEventSubSubscription( + $bearer, + $secret, + $callback, + sprintf('channel.shoutout.%s', $eventType), + '1', [ 'broadcaster_user_id' => $twitchId, 'moderator_user_id' => $moderatorId,