From ecf0e37e460d173a7474096e501b6f652c371331 Mon Sep 17 00:00:00 2001 From: Brandin Arsenault Date: Fri, 2 Dec 2022 22:44:46 -0400 Subject: [PATCH 1/2] Add Charity APIs/Subs, Chat and Moderation API Additions --- spec/TwitchApi/Resources/CharityApiSpec.php | 36 +++++++++ spec/TwitchApi/Resources/ChatApiSpec.php | 12 +++ spec/TwitchApi/Resources/EventSubApiSpec.php | 36 +++++++++ .../TwitchApi/Resources/ModerationApiSpec.php | 12 +++ spec/TwitchApi/TwitchApiSpec.php | 6 ++ src/Resources/CharityApi.php | 43 +++++++++++ src/Resources/ChatApi.php | 23 ++++++ src/Resources/EventSubApi.php | 75 +++++++++++++++++++ src/Resources/ModerationApi.php | 29 +++++++ src/TwitchApi.php | 8 ++ 10 files changed, 280 insertions(+) create mode 100644 spec/TwitchApi/Resources/CharityApiSpec.php create mode 100644 src/Resources/CharityApi.php diff --git a/spec/TwitchApi/Resources/CharityApiSpec.php b/spec/TwitchApi/Resources/CharityApiSpec.php new file mode 100644 index 0000000..89efda9 --- /dev/null +++ b/spec/TwitchApi/Resources/CharityApiSpec.php @@ -0,0 +1,36 @@ +beConstructedWith($guzzleClient, $requestGenerator); + $guzzleClient->send($request)->willReturn($response); + } + + function it_should_get_charity_campaigns(RequestGenerator $requestGenerator, Request $request, Response $response) + { + $requestGenerator->generate('GET', 'charity/campaigns', 'TEST_TOKEN', [['key' => 'broadcaster_id', 'value' => '123']], [])->willReturn($request); + $this->getCharityCampaign('TEST_TOKEN', '123')->shouldBe($response); + } + + function it_should_get_charity_campaign_donations(RequestGenerator $requestGenerator, Request $request, Response $response) + { + $requestGenerator->generate('GET', 'charity/donations', 'TEST_TOKEN', [['key' => 'broadcaster_id', 'value' => '123']], [])->willReturn($request); + $this->getCharityCampaignDonations('TEST_TOKEN', '123')->shouldBe($response); + } + + function it_should_get_charity_campaign_donations_with_opts(RequestGenerator $requestGenerator, Request $request, Response $response) + { + $requestGenerator->generate('GET', 'charity/donations', 'TEST_TOKEN', [['key' => 'broadcaster_id', 'value' => '123'], ['key' => 'first', 'value' => 100], ['key' => 'after', 'value' => 'abc']], [])->willReturn($request); + $this->getCharityCampaignDonations('TEST_TOKEN', '123', 100, 'abc')->shouldBe($response); + } +} diff --git a/spec/TwitchApi/Resources/ChatApiSpec.php b/spec/TwitchApi/Resources/ChatApiSpec.php index 1464164..8f63576 100644 --- a/spec/TwitchApi/Resources/ChatApiSpec.php +++ b/spec/TwitchApi/Resources/ChatApiSpec.php @@ -105,4 +105,16 @@ function it_should_update_a_users_chat_color(RequestGenerator $requestGenerator, $requestGenerator->generate('PUT', 'chat/color', 'TEST_TOKEN', [['key' => 'user_id', 'value' => '123'], ['key' => 'color', 'value' => 'red']], [])->willReturn($request); $this->updateUserChatColor('TEST_TOKEN', '123', 'red')->shouldBe($response); } + + function it_should_get_chatters(RequestGenerator $requestGenerator, Request $request, Response $response) + { + $requestGenerator->generate('GET', 'chat/chatters', 'TEST_TOKEN', [['key' => 'broadcaster_id', 'value' => '123'], ['key' => 'moderator_id', 'value' => '456']], [])->willReturn($request); + $this->getChatters('TEST_TOKEN', '123', '456')->shouldBe($response); + } + + function it_should_get_chatters_with_opts(RequestGenerator $requestGenerator, Request $request, Response $response) + { + $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); + } } diff --git a/spec/TwitchApi/Resources/EventSubApiSpec.php b/spec/TwitchApi/Resources/EventSubApiSpec.php index 4c28bcc..8a11339 100644 --- a/spec/TwitchApi/Resources/EventSubApiSpec.php +++ b/spec/TwitchApi/Resources/EventSubApiSpec.php @@ -300,4 +300,40 @@ function it_should_subscribe_to_drop_entitelement_grant_with_opts(RequestGenerat $this->createEventSubSubscription('drop.entitlement.grant', '1', ['organization_id' => '123', 'category_id' => '456', 'campaign_id' => '789'], $requestGenerator)->willReturn($request); $this->subscribeToDropEntitlementGrant($this->bearer, $this->secret, $this->callback, '123', '456', '789')->shouldBe($response); } + + 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->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->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->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->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->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->subscribeToChannelShieldModeEnd($this->bearer, $this->secret, $this->callback, '12345', '54321')->shouldBe($response); + } } diff --git a/spec/TwitchApi/Resources/ModerationApiSpec.php b/spec/TwitchApi/Resources/ModerationApiSpec.php index 78052c3..1413cea 100644 --- a/spec/TwitchApi/Resources/ModerationApiSpec.php +++ b/spec/TwitchApi/Resources/ModerationApiSpec.php @@ -171,4 +171,16 @@ function it_should_get_moderators_with_opts(RequestGenerator $requestGenerator, $requestGenerator->generate('GET', 'moderation/moderators', 'TEST_TOKEN', [['key' => 'broadcaster_id', 'value' => '123'], ['key' => 'user_id', 'value' => 'abc'], ['key' => 'user_id', 'value' => 'def'], ['key' => 'after', 'value' => 'abc'], ['key' => 'first', 'value' => '100']], [])->willReturn($request); $this->getModerators('TEST_TOKEN', '123', ['abc', 'def'], 'abc', '100')->shouldBe($response); } + + function it_should_get_shield_mode_status(RequestGenerator $requestGenerator, Request $request, Response $response) + { + $requestGenerator->generate('GET', 'moderation/shield_mode', 'TEST_TOKEN', [['key' => 'broadcaster_id', 'value' => '123'], ['key' => 'moderator_id', 'value' => '456']], [])->willReturn($request); + $this->getShieldModeStatus('TEST_TOKEN', '123', '456')->shouldBe($response); + } + + function it_should_update_shield_mode_status(RequestGenerator $requestGenerator, Request $request, Response $response) + { + $requestGenerator->generate('PUT', 'moderation/shield_mode', 'TEST_TOKEN', [['key' => 'broadcaster_id', 'value' => '123'], ['key' => 'moderator_id', 'value' => '456']], [['key' => 'is_active', 'value' => true]])->willReturn($request); + $this->updateShieldModeStatus('TEST_TOKEN', '123', '456', true)->shouldBe($response); + } } diff --git a/spec/TwitchApi/TwitchApiSpec.php b/spec/TwitchApi/TwitchApiSpec.php index a9d7520..21fe9a8 100644 --- a/spec/TwitchApi/TwitchApiSpec.php +++ b/spec/TwitchApi/TwitchApiSpec.php @@ -10,6 +10,7 @@ use TwitchApi\Resources\BitsApi; use TwitchApi\Resources\ChannelPointsApi; use TwitchApi\Resources\ChannelsApi; +use TwitchApi\Resources\CharityApi; use TwitchApi\Resources\ChatApi; use TwitchApi\Resources\ClipsApi; use TwitchApi\Resources\EntitlementsApi; @@ -70,6 +71,11 @@ function it_should_provide_channels_api() $this->getChannelsApi()->shouldBeAnInstanceOf(ChannelsApi::class); } + function it_should_provide_charity_api() + { + $this->getCharityApi()->shouldBeAnInstanceOf(CharityApi::class); + } + function it_should_provide_chat_api() { $this->getChatApi()->shouldBeAnInstanceOf(ChatApi::class); diff --git a/src/Resources/CharityApi.php b/src/Resources/CharityApi.php new file mode 100644 index 0000000..8732335 --- /dev/null +++ b/src/Resources/CharityApi.php @@ -0,0 +1,43 @@ + 'broadcaster_id', 'value' => $broadcasterId]; + + return $this->getApi('charity/campaigns', $bearer, $queryParamsMap); + } + + /** + * @throws GuzzleException + * @link https://dev.twitch.tv/docs/api/reference#get-charity-campaign-donations + */ + public function getCharityCampaignDonations(string $bearer, string $broadcasterId, int $first = null, string $after = null): ResponseInterface + { + $queryParamsMap = []; + $queryParamsMap[] = ['key' => 'broadcaster_id', 'value' => $broadcasterId]; + + if ($first) { + $queryParamsMap[] = ['key' => 'first', 'value' => $first]; + } + + if ($after) { + $queryParamsMap[] = ['key' => 'after', 'value' => $after]; + } + + return $this->getApi('charity/donations', $bearer, $queryParamsMap); + } +} diff --git a/src/Resources/ChatApi.php b/src/Resources/ChatApi.php index 9a49196..8f322fe 100644 --- a/src/Resources/ChatApi.php +++ b/src/Resources/ChatApi.php @@ -156,4 +156,27 @@ public function updateUserChatColor(string $bearer, string $userId, string $colo return $this->putApi('chat/color', $bearer, $queryParamsMap); } + + /** + * @throws GuzzleException + * @link https://dev.twitch.tv/docs/api/reference#get-chatters + */ + public function getChatters(string $bearer, string $broadcasterId, string $moderatorId, int $first = null, string $after = null): ResponseInterface + { + $queryParamsMap = []; + + $queryParamsMap[] = ['key' => 'broadcaster_id', 'value' => $broadcasterId]; + + $queryParamsMap[] = ['key' => 'moderator_id', 'value' => $moderatorId]; + + if ($first) { + $queryParamsMap[] = ['key' => 'first', 'value' => $first]; + } + + if ($after) { + $queryParamsMap[] = ['key' => 'after', 'value' => $after]; + } + + return $this->getApi('chat/chatters', $bearer, $queryParamsMap); + } } diff --git a/src/Resources/EventSubApi.php b/src/Resources/EventSubApi.php index c6e0877..3285549 100644 --- a/src/Resources/EventSubApi.php +++ b/src/Resources/EventSubApi.php @@ -443,6 +443,54 @@ public function subscribeToChannelGoalEnd(string $bearer, string $secret, string return $this->subscribeToChannelGoal($bearer, $secret, $callback, $twitchId, 'end'); } + /** + * @link https://dev.twitch.tv/docs/eventsub/eventsub-subscription-types#channelcharity_campaignstart + */ + public function subscribeToChannelCharityCampaignStart(string $bearer, string $secret, string $callback, string $twitchId): ResponseInterface + { + return $this->subscribeToChannelCharityCampaign($bearer, $secret, $callback, $twitchId, 'start'); + } + + /** + * @link https://dev.twitch.tv/docs/eventsub/eventsub-subscription-types#channelcharity_campaignprogress + */ + public function subscribeToChannelCharityCampaignProgress(string $bearer, string $secret, string $callback, string $twitchId): ResponseInterface + { + return $this->subscribeToChannelCharityCampaign($bearer, $secret, $callback, $twitchId, 'progress'); + } + + /** + * @link https://dev.twitch.tv/docs/eventsub/eventsub-subscription-types#channelcharity_campaignstop + */ + public function subscribeToChannelCharityCampaignStop(string $bearer, string $secret, string $callback, string $twitchId): ResponseInterface + { + return $this->subscribeToChannelCharityCampaign($bearer, $secret, $callback, $twitchId, 'stop'); + } + + /** + * @link https://dev.twitch.tv/docs/eventsub/eventsub-subscription-types#channelcharity_campaigndonate + */ + public function subscribeToChannelCharityCampaignDonate(string $bearer, string $secret, string $callback, string $twitchId): ResponseInterface + { + return $this->subscribeToChannelCharityCampaign($bearer, $secret, $callback, $twitchId, 'donate'); + } + + /** + * @link https://dev.twitch.tv/docs/eventsub/eventsub-subscription-types#channelshield_modebegin + */ + public function subscribeToChannelShieldModeBegin(string $bearer, string $secret, string $callback, string $twitchId, string $moderatorId): ResponseInterface + { + return $this->subscribeToChannelShieldMode($bearer, $secret, $callback, $twitchId, $moderatorId, 'begin'); + } + + /** + * @link https://dev.twitch.tv/docs/eventsub/eventsub-subscription-types#channelshield_modeend + */ + public function subscribeToChannelShieldModeEnd(string $bearer, string $secret, string $callback, string $twitchId, string $moderatorId): ResponseInterface + { + return $this->subscribeToChannelShieldMode($bearer, $secret, $callback, $twitchId, $moderatorId, 'end'); + } + /** * @link https://dev.twitch.tv/docs/eventsub/eventsub-subscription-types/#dropentitlementgrant */ @@ -600,4 +648,31 @@ private function subscribeToChannelGoal(string $bearer, string $secret, string $ ['broadcaster_user_id' => $twitchId], ); } + + private function subscribeToChannelCharityCampaign(string $bearer, string $secret, string $callback, string $twitchId, string $eventType): ResponseInterface + { + return $this->createEventSubSubscription( + $bearer, + $secret, + $callback, + sprintf('channel.charity_campaign.%s', $eventType), + 'beta', + ['broadcaster_user_id' => $twitchId], + ); + } + + private function subscribeToChannelShieldMode(string $bearer, string $secret, string $callback, string $twitchId, string $moderatorId, string $eventType): ResponseInterface + { + return $this->createEventSubSubscription( + $bearer, + $secret, + $callback, + sprintf('channel.shield_mode.%s', $eventType), + 'beta', + [ + 'broadcaster_user_id' => $twitchId, + 'moderator_user_id' => $moderatorId + ], + ); + } } diff --git a/src/Resources/ModerationApi.php b/src/Resources/ModerationApi.php index 4ebb706..6aae1b0 100644 --- a/src/Resources/ModerationApi.php +++ b/src/Resources/ModerationApi.php @@ -306,4 +306,33 @@ public function removeChannelVip(string $bearer, string $broadcasterId, string $ return $this->deleteApi('channels/vips', $bearer, $queryParamsMap); } + + /** + * @throws GuzzleException + * @link https://dev.twitch.tv/docs/api/reference#get-shield-mode-status + */ + public function getShieldModeStatus(string $bearer, string $broadcasterId, string $moderatorId): ResponseInterface + { + $queryParamsMap = []; + $queryParamsMap[] = ['key' => 'broadcaster_id', 'value' => $broadcasterId]; + $queryParamsMap[] = ['key' => 'moderator_id', 'value' => $moderatorId]; + + return $this->getApi('moderation/shield_mode', $bearer, $queryParamsMap); + } + + /** + * @throws GuzzleException + * @link https://dev.twitch.tv/docs/api/reference#update-shield-mode-status + */ + public function updateShieldModeStatus(string $bearer, string $broadcasterId, string $moderatorId, bool $isActive): ResponseInterface + { + $queryParamsMap = []; + $queryParamsMap[] = ['key' => 'broadcaster_id', 'value' => $broadcasterId]; + $queryParamsMap[] = ['key' => 'moderator_id', 'value' => $moderatorId]; + + $bodyParamsMap = []; + $bodyParamsMap[] = ['key' => 'is_active', 'value' => $isActive]; + + return $this->putApi('moderation/shield_mode', $bearer, $queryParamsMap, $bodyParamsMap); + } } diff --git a/src/TwitchApi.php b/src/TwitchApi.php index 5aad331..96c8c9d 100644 --- a/src/TwitchApi.php +++ b/src/TwitchApi.php @@ -11,6 +11,7 @@ use TwitchApi\Resources\BitsApi; use TwitchApi\Resources\ChannelPointsApi; use TwitchApi\Resources\ChannelsApi; +use TwitchApi\Resources\CharityApi; use TwitchApi\Resources\ChatApi; use TwitchApi\Resources\ClipsApi; use TwitchApi\Resources\EntitlementsApi; @@ -41,6 +42,7 @@ class TwitchApi private $bitsApi; private $channelPointsApi; private $channelsApi; + private $charityApi; private $chatApi; private $clipsApi; private $entitlementsApi; @@ -72,6 +74,7 @@ public function __construct(HelixGuzzleClient $helixGuzzleClient, string $client $this->bitsApi = new BitsApi($helixGuzzleClient, $requestGenerator); $this->channelPointsApi = new ChannelPointsApi($helixGuzzleClient, $requestGenerator); $this->channelsApi = new ChannelsApi($helixGuzzleClient, $requestGenerator); + $this->charityApi = new CharityApi($helixGuzzleClient, $requestGenerator); $this->chatApi = new ChatApi($helixGuzzleClient, $requestGenerator); $this->clipsApi = new ClipsApi($helixGuzzleClient, $requestGenerator); $this->entitlementsApi = new EntitlementsApi($helixGuzzleClient, $requestGenerator); @@ -125,6 +128,11 @@ public function getChannelsApi(): ChannelsApi return $this->channelsApi; } + public function getCharityApi(): CharityApi + { + return $this->charityApi; + } + public function getChatApi(): ChatApi { return $this->chatApi; From d5087a9ce38b2f10b17233f25d2450143326b916 Mon Sep 17 00:00:00 2001 From: Brandin Arsenault Date: Fri, 2 Dec 2022 22:52:54 -0400 Subject: [PATCH 2/2] CS Fixes --- src/Resources/CharityApi.php | 2 +- src/Resources/EventSubApi.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Resources/CharityApi.php b/src/Resources/CharityApi.php index 8732335..997db4f 100644 --- a/src/Resources/CharityApi.php +++ b/src/Resources/CharityApi.php @@ -29,7 +29,7 @@ public function getCharityCampaignDonations(string $bearer, string $broadcasterI { $queryParamsMap = []; $queryParamsMap[] = ['key' => 'broadcaster_id', 'value' => $broadcasterId]; - + if ($first) { $queryParamsMap[] = ['key' => 'first', 'value' => $first]; } diff --git a/src/Resources/EventSubApi.php b/src/Resources/EventSubApi.php index 3285549..89a05e6 100644 --- a/src/Resources/EventSubApi.php +++ b/src/Resources/EventSubApi.php @@ -671,7 +671,7 @@ private function subscribeToChannelShieldMode(string $bearer, string $secret, st 'beta', [ 'broadcaster_user_id' => $twitchId, - 'moderator_user_id' => $moderatorId + 'moderator_user_id' => $moderatorId, ], ); }