twitchrb 1.10.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +2 -2
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +104 -1
- data/Gemfile.lock +5 -5
- data/README.md +360 -45
- data/lib/twitch/client.rb +109 -20
- data/lib/twitch/collection.rb +58 -11
- data/lib/twitch/error_generator.rb +6 -4
- data/lib/twitch/eventsub_webhook.rb +140 -0
- data/lib/twitch/oauth.rb +50 -15
- data/lib/twitch/object.rb +28 -0
- data/lib/twitch/objects/ad_schedule.rb +4 -0
- data/lib/twitch/objects/analytics_report.rb +4 -0
- data/lib/twitch/objects/bits_leaderboard_entry.rb +4 -0
- data/lib/twitch/objects/charity_donation.rb +4 -0
- data/lib/twitch/objects/chat_settings.rb +4 -0
- data/lib/twitch/objects/cheermote.rb +4 -0
- data/lib/twitch/objects/content_classification_label.rb +4 -0
- data/lib/twitch/objects/drops_entitlement.rb +4 -0
- data/lib/twitch/objects/drops_entitlement_update.rb +4 -0
- data/lib/twitch/objects/extension.rb +4 -0
- data/lib/twitch/objects/extension_bits_product.rb +4 -0
- data/lib/twitch/objects/extension_configuration_segment.rb +4 -0
- data/lib/twitch/objects/extension_live_channel.rb +4 -0
- data/lib/twitch/objects/extension_secret.rb +4 -0
- data/lib/twitch/objects/extension_transaction.rb +4 -0
- data/lib/twitch/objects/guest_star_invite.rb +4 -0
- data/lib/twitch/objects/guest_star_session.rb +4 -0
- data/lib/twitch/objects/guest_star_settings.rb +4 -0
- data/lib/twitch/objects/shield_mode_status.rb +4 -0
- data/lib/twitch/objects/{tag.rb → team.rb} +1 -1
- data/lib/twitch/objects/user_active_extensions.rb +4 -0
- data/lib/twitch/objects/user_extension.rb +4 -0
- data/lib/twitch/resource.rb +49 -9
- data/lib/twitch/resources/ads.rb +18 -0
- data/lib/twitch/resources/analytics.rb +19 -0
- data/lib/twitch/resources/announcements.rb +1 -1
- data/lib/twitch/resources/automod.rb +8 -8
- data/lib/twitch/resources/badges.rb +3 -3
- data/lib/twitch/resources/banned_users.rb +4 -4
- data/lib/twitch/resources/bits.rb +16 -0
- data/lib/twitch/resources/blocked_terms.rb +5 -5
- data/lib/twitch/resources/channels.rb +7 -7
- data/lib/twitch/resources/charity_campaigns.rb +9 -1
- data/lib/twitch/resources/chat_messages.rb +1 -1
- data/lib/twitch/resources/chat_settings.rb +20 -0
- data/lib/twitch/resources/chatters.rb +1 -1
- data/lib/twitch/resources/clips.rb +3 -9
- data/lib/twitch/resources/content_classification_labels.rb +8 -0
- data/lib/twitch/resources/custom_power_ups.rb +1 -1
- data/lib/twitch/resources/custom_reward_redemptions.rb +3 -4
- data/lib/twitch/resources/custom_rewards.rb +5 -5
- data/lib/twitch/resources/drops_entitlements.rb +17 -0
- data/lib/twitch/resources/emotes.rb +5 -5
- data/lib/twitch/resources/eventsub_conduits.rb +14 -4
- data/lib/twitch/resources/eventsub_subscriptions.rb +9 -13
- data/lib/twitch/resources/extensions.rb +99 -0
- data/lib/twitch/resources/games.rb +5 -7
- data/lib/twitch/resources/goals.rb +1 -1
- data/lib/twitch/resources/guest_star.rb +102 -0
- data/lib/twitch/resources/moderators.rb +4 -4
- data/lib/twitch/resources/pinned_chat_messages.rb +4 -11
- data/lib/twitch/resources/polls.rb +1 -1
- data/lib/twitch/resources/predictions.rb +1 -1
- data/lib/twitch/resources/raids.rb +3 -4
- data/lib/twitch/resources/search.rb +2 -2
- data/lib/twitch/resources/shield_mode.rb +18 -0
- data/lib/twitch/resources/shoutouts.rb +1 -1
- data/lib/twitch/resources/stream_markers.rb +1 -1
- data/lib/twitch/resources/stream_schedule.rb +4 -5
- data/lib/twitch/resources/streams.rb +2 -2
- data/lib/twitch/resources/subscriptions.rb +13 -2
- data/lib/twitch/resources/suspicious_users.rb +6 -2
- data/lib/twitch/resources/teams.rb +20 -0
- data/lib/twitch/resources/unban_requests.rb +2 -2
- data/lib/twitch/resources/users.rb +37 -43
- data/lib/twitch/resources/videos.rb +3 -3
- data/lib/twitch/resources/vips.rb +3 -3
- data/lib/twitch/resources/warnings.rb +2 -2
- data/lib/twitch/resources/whispers.rb +1 -1
- data/lib/twitch/version.rb +1 -1
- data/lib/twitch.rb +33 -9
- data/twitchrb.gemspec +5 -5
- metadata +42 -18
- data/lib/twitch/objects/banned_event.rb +0 -4
- data/lib/twitch/objects/followed_user.rb +0 -4
- data/lib/twitch/objects/hype_train_event.rb +0 -4
- data/lib/twitch/objects/moderator_event.rb +0 -4
- data/lib/twitch/resources/banned_events.rb +0 -8
- data/lib/twitch/resources/hype_train_events.rb +0 -10
- data/lib/twitch/resources/moderator_events.rb +0 -9
- data/lib/twitch/resources/tags.rb +0 -18
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# TwitchRB
|
|
2
2
|
|
|
3
|
-
[](https://github.com/d34ndev/twitchrb/actions/workflows/ci.yml)
|
|
4
4
|
[](https://badge.fury.io/rb/twitchrb)
|
|
5
5
|
[](https://rubygems.org/gems/twitchrb)
|
|
6
6
|
|
|
@@ -14,6 +14,8 @@ Add this line to your application's Gemfile:
|
|
|
14
14
|
gem "twitchrb"
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
+
Upgrading from 1.x? Version 2.0 has breaking changes. See [Upgrading from 1.x](CHANGELOG.md#upgrading-from-1x) in the changelog.
|
|
18
|
+
|
|
17
19
|
## Usage
|
|
18
20
|
|
|
19
21
|
### Set Client Details
|
|
@@ -26,17 +28,46 @@ An access token is required because the Helix API requires authentication.
|
|
|
26
28
|
@client = Twitch::Client.new(client_id: "abc123", access_token: "xyz123")
|
|
27
29
|
```
|
|
28
30
|
|
|
31
|
+
Requests time out after 30 seconds (10 seconds to open the connection) by default, raising
|
|
32
|
+
`Faraday::TimeoutError` or `Faraday::ConnectionFailed`. Both can be changed on `Twitch::Client` and `Twitch::OAuth`:
|
|
33
|
+
|
|
34
|
+
```ruby
|
|
35
|
+
@client = Twitch::Client.new(client_id: "abc123", access_token: "xyz123", timeout: 10, open_timeout: 5)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
#### Refreshing User Access Tokens
|
|
39
|
+
|
|
40
|
+
User access tokens expire after a few hours. Pass the `refresh_token` and your `client_secret` and the client
|
|
41
|
+
will refresh an expired token automatically, then retry the request. Twitch may issue a new refresh token each
|
|
42
|
+
time, so use `on_token_refresh` to store the new tokens:
|
|
43
|
+
|
|
44
|
+
```ruby
|
|
45
|
+
@client = Twitch::Client.new(
|
|
46
|
+
client_id: "abc123",
|
|
47
|
+
client_secret: "your-client-secret", # omit for public clients
|
|
48
|
+
access_token: user.twitch_access_token,
|
|
49
|
+
refresh_token: user.twitch_refresh_token,
|
|
50
|
+
on_token_refresh: ->(token) {
|
|
51
|
+
user.update!(twitch_access_token: token.access_token, twitch_refresh_token: token.refresh_token)
|
|
52
|
+
}
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
# Or refresh manually
|
|
56
|
+
@client.refresh_access_token!
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The client refreshes once per expired token, even across threads. If the refresh token itself is invalid (e.g.
|
|
60
|
+
the user disconnected your app), the error from Twitch is raised, e.g. `Twitch::Errors::BadRequestError`.
|
|
61
|
+
|
|
29
62
|
#### User vs. App Access Tokens
|
|
30
63
|
|
|
31
64
|
Most endpoints accept a **user access token** — issued for a specific Twitch user via the
|
|
32
65
|
[authorization code](https://dev.twitch.tv/docs/authentication/getting-tokens-oauth/#authorization-code-grant-flow)
|
|
33
66
|
or [device code](https://dev.twitch.tv/docs/authentication/getting-tokens-oauth/#device-code-grant-flow) flows,
|
|
34
|
-
and required for anything that acts on behalf of a user (
|
|
67
|
+
and required for anything that acts on behalf of a user (managing channels, polls, rewards, etc.).
|
|
35
68
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
each section below. App tokens are obtained with the `client_credentials` grant and need only your
|
|
39
|
-
Client ID and Client Secret:
|
|
69
|
+
An **app access token** is issued to your application, not a user. App tokens are obtained with the
|
|
70
|
+
`client_credentials` grant and need only your Client ID and Client Secret:
|
|
40
71
|
|
|
41
72
|
```ruby
|
|
42
73
|
oauth = Twitch::OAuth.new(client_id: "abc123", client_secret: "your-client-secret")
|
|
@@ -48,6 +79,25 @@ token = oauth.create(grant_type: "client_credentials")
|
|
|
48
79
|
App tokens expire (typically after ~60 days). Use `oauth.validate(token: ...)` to check the remaining
|
|
49
80
|
lifetime, and `oauth.create(grant_type: "client_credentials")` to mint a fresh one when needed.
|
|
50
81
|
|
|
82
|
+
**These require an app access token:**
|
|
83
|
+
|
|
84
|
+
- EventSub over webhooks or conduits: `eventsub_subscriptions` and `eventsub_conduits` (including shards).
|
|
85
|
+
EventSub over WebSockets requires a user access token instead.
|
|
86
|
+
- `users.authorization`
|
|
87
|
+
- `extensions.transactions`, and `extensions.bits_products`/`update_bits_product` (the token's Client ID must be the extension's)
|
|
88
|
+
|
|
89
|
+
**These also accept an app access token**, as long as the user in the request (e.g. `sender_id` or
|
|
90
|
+
`moderator_id`) has previously authorized your app with the required scope through one of the user token flows.
|
|
91
|
+
This is how chatbots can act without storing each user's token. Chat endpoints need the bot account to have
|
|
92
|
+
granted `user:bot`, and the broadcaster to have granted `channel:bot` or made the bot a moderator — see
|
|
93
|
+
[Chatbots](https://dev.twitch.tv/docs/chat/authenticating/) for details.
|
|
94
|
+
|
|
95
|
+
- Chat: `chat_messages.create`, `chat_messages.delete`, `announcements.create`, `shoutouts.create`,
|
|
96
|
+
`pinned_chat_messages` (all methods), `chatters.list`, `chat_settings.update`
|
|
97
|
+
- Moderation: `automod` (all methods), `banned_users` (all methods), `blocked_terms` (all methods),
|
|
98
|
+
`moderators.channels`, `shield_mode` (all methods), `warnings.create`, `suspicious_users` (all methods)
|
|
99
|
+
- Ads: `channels.commercial`, `ads.schedule`, `ads.snooze`
|
|
100
|
+
|
|
51
101
|
### Resources
|
|
52
102
|
|
|
53
103
|
The gem maps as closely as we can to the Twitch API so you can easily convert API examples to gem code.
|
|
@@ -85,11 +135,38 @@ results.last
|
|
|
85
135
|
results.cursor
|
|
86
136
|
#=> "abc123"
|
|
87
137
|
|
|
88
|
-
# Retrieve the next page
|
|
138
|
+
# Retrieve the next page manually
|
|
89
139
|
@client.clips.list(broadcaster_id: 123, after: results.cursor)
|
|
90
140
|
#=> Twitch::Collection
|
|
91
141
|
```
|
|
92
142
|
|
|
143
|
+
#### Automatic Pagination
|
|
144
|
+
|
|
145
|
+
Collections from paginated endpoints can fetch their following pages for you. Each extra page is a separate
|
|
146
|
+
API request (and counts towards your rate limit), so use `first:` to request up to 100 items per page.
|
|
147
|
+
|
|
148
|
+
```ruby
|
|
149
|
+
followers = @client.channels.followers(broadcaster_id: 123, first: 100)
|
|
150
|
+
|
|
151
|
+
# Fetch the next page, or nil on the last page
|
|
152
|
+
followers.next_page? #=> true
|
|
153
|
+
followers.next_page #=> Twitch::Collection
|
|
154
|
+
|
|
155
|
+
# Iterate over every item across all pages. Pages are fetched lazily, only as needed.
|
|
156
|
+
followers.auto_paginate.each { |follower| puts follower.user_name }
|
|
157
|
+
|
|
158
|
+
# Stop after 250 items, without fetching any more pages than needed
|
|
159
|
+
followers.auto_paginate.first(250)
|
|
160
|
+
|
|
161
|
+
# Get every item as an array
|
|
162
|
+
followers.auto_paginate.to_a
|
|
163
|
+
|
|
164
|
+
# Iterate page by page
|
|
165
|
+
followers.each_page do |page|
|
|
166
|
+
puts "#{page.data.size} followers on this page"
|
|
167
|
+
end
|
|
168
|
+
```
|
|
169
|
+
|
|
93
170
|
### Rate Limiting
|
|
94
171
|
|
|
95
172
|
The Twitch API has rate limits to ensure fair usage. TwitchRB automatically tracks rate limit information from API responses and can warn you when approaching limits.
|
|
@@ -168,33 +245,59 @@ The `rate_limiter` object has several useful methods:
|
|
|
168
245
|
|
|
169
246
|
### OAuth
|
|
170
247
|
|
|
171
|
-
This library includes the ability to create, refresh and revoke OAuth tokens.
|
|
248
|
+
This library includes the ability to create, refresh, validate and revoke OAuth tokens.
|
|
249
|
+
|
|
250
|
+
Failed token requests raise the same errors as API requests (e.g. `Twitch::Errors::BadRequestError`),
|
|
251
|
+
with Twitch's message available as `error.twitch_error_message`.
|
|
172
252
|
|
|
173
253
|
```ruby
|
|
174
254
|
# Firstly, set the client details
|
|
255
|
+
# client_secret can be omitted for public clients using the device code flow
|
|
175
256
|
@oauth = Twitch::OAuth.new(client_id: "", client_secret: "")
|
|
176
257
|
|
|
177
|
-
# Create
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
258
|
+
# Create an app access token (client credentials grant flow)
|
|
259
|
+
@oauth.create(grant_type: "client_credentials")
|
|
260
|
+
|
|
261
|
+
# Exchange the code from the authorization code grant flow for a user access token
|
|
262
|
+
# https://dev.twitch.tv/docs/authentication/getting-tokens-oauth/#authorization-code-grant-flow
|
|
263
|
+
token = @oauth.exchange_code(code: params[:code], redirect_uri: "http://localhost:3000/callback")
|
|
264
|
+
token.access_token
|
|
265
|
+
token.refresh_token
|
|
181
266
|
|
|
182
267
|
# Refresh a Token
|
|
183
268
|
@oauth.refresh(refresh_token: "")
|
|
184
269
|
|
|
185
|
-
# Device Code Grant Flow
|
|
186
|
-
# scopes is required and is a space-delimited list of scopes
|
|
187
|
-
# https://dev.twitch.tv/docs/authentication/getting-tokens-oauth/#device-code-grant-flow
|
|
188
|
-
@oauth.device(scopes: "bits:read channel:read:subscriptions")
|
|
189
|
-
|
|
190
270
|
# Validate an Access Token
|
|
191
271
|
# Returns false if the token is invalid
|
|
192
272
|
@oauth.validate(token: "")
|
|
193
273
|
|
|
194
274
|
# Revoke a Token
|
|
275
|
+
# Returns false if the token couldn't be revoked
|
|
195
276
|
@oauth.revoke(token: "")
|
|
196
277
|
```
|
|
197
278
|
|
|
279
|
+
#### Device Code Grant Flow
|
|
280
|
+
|
|
281
|
+
For apps with limited input, such as CLIs, set-top boxes or games.
|
|
282
|
+
See [the Twitch docs](https://dev.twitch.tv/docs/authentication/getting-tokens-oauth/#device-code-grant-flow).
|
|
283
|
+
|
|
284
|
+
```ruby
|
|
285
|
+
# scopes can be an array or a space-delimited string
|
|
286
|
+
scopes = ["user:read:email", "chat:read"]
|
|
287
|
+
device = @oauth.device(scopes: scopes)
|
|
288
|
+
|
|
289
|
+
puts "Go to #{device.verification_uri} and enter #{device.user_code}"
|
|
290
|
+
|
|
291
|
+
# Poll until the user has authorized the app
|
|
292
|
+
token = begin
|
|
293
|
+
sleep device.interval
|
|
294
|
+
@oauth.device_token(device_code: device.device_code, scopes: scopes)
|
|
295
|
+
rescue Twitch::Errors::BadRequestError => e
|
|
296
|
+
retry if e.twitch_error_message == "authorization_pending"
|
|
297
|
+
raise
|
|
298
|
+
end
|
|
299
|
+
```
|
|
300
|
+
|
|
198
301
|
### Users
|
|
199
302
|
|
|
200
303
|
```ruby
|
|
@@ -254,6 +357,19 @@ This library includes the ability to create, refresh and revoke OAuth tokens.
|
|
|
254
357
|
# #<Twitch::UserAuthorization user_id="72938118", user_name="deanpcmad", user_login="deanpcmad", scopes=["user:read:email"], has_authorized=true>
|
|
255
358
|
@client.users.authorization(id: 123)
|
|
256
359
|
@client.users.authorization(ids: [123, 321])
|
|
360
|
+
|
|
361
|
+
# Gets all extensions the authenticated user has installed, active or not
|
|
362
|
+
# Required scope: user:read:broadcast or user:edit:broadcast (needed to include inactive extensions)
|
|
363
|
+
@client.users.extensions
|
|
364
|
+
|
|
365
|
+
# Gets the active extensions for a user, or the authenticated user if user_id is omitted
|
|
366
|
+
@client.users.active_extensions(user_id: 123)
|
|
367
|
+
|
|
368
|
+
# Updates the authenticated user's active extensions
|
|
369
|
+
# Required scope: user:edit:broadcast
|
|
370
|
+
@client.users.update_extensions(data: {
|
|
371
|
+
panel: { "1" => { active: true, id: "abc123", version: "1.0.0" } }
|
|
372
|
+
})
|
|
257
373
|
```
|
|
258
374
|
|
|
259
375
|
### Channels
|
|
@@ -437,6 +553,54 @@ end
|
|
|
437
553
|
@client.eventsub_subscriptions.delete(id: "abc12-abc12-abc12")
|
|
438
554
|
```
|
|
439
555
|
|
|
556
|
+
### EventSub Webhooks
|
|
557
|
+
|
|
558
|
+
When Twitch sends EventSub notifications to your webhook callback, you must verify each request came from Twitch
|
|
559
|
+
before trusting it. `Twitch::EventsubWebhook` checks the HMAC signature using the `secret` you passed when creating
|
|
560
|
+
the subscription, and rejects messages older than 10 minutes to guard against replay attacks.
|
|
561
|
+
|
|
562
|
+
Pass the **raw** request body, as the signature covers the exact bytes Twitch sent. `headers` can be a Hash,
|
|
563
|
+
a Rack env, or Rails' `request.headers`.
|
|
564
|
+
|
|
565
|
+
```ruby
|
|
566
|
+
# Rails example
|
|
567
|
+
class TwitchWebhooksController < ApplicationController
|
|
568
|
+
skip_forgery_protection
|
|
569
|
+
|
|
570
|
+
def create
|
|
571
|
+
webhook = Twitch::EventsubWebhook.new(
|
|
572
|
+
secret: ENV["TWITCH_EVENTSUB_SECRET"],
|
|
573
|
+
headers: request.headers,
|
|
574
|
+
body: request.raw_post
|
|
575
|
+
)
|
|
576
|
+
|
|
577
|
+
return head :forbidden unless webhook.valid?
|
|
578
|
+
|
|
579
|
+
if webhook.verification?
|
|
580
|
+
# Twitch confirms you own the callback when you create a subscription
|
|
581
|
+
render plain: webhook.challenge
|
|
582
|
+
elsif webhook.notification?
|
|
583
|
+
# Twitch may send a message more than once, so skip message IDs you've already processed
|
|
584
|
+
# webhook.subscription_type #=> "channel.follow"
|
|
585
|
+
# webhook.event #=> #<Twitch::Object user_id="1234", user_login="cool_user", ...>
|
|
586
|
+
head :no_content
|
|
587
|
+
elsif webhook.revocation?
|
|
588
|
+
# webhook.subscription.status #=> "authorization_revoked"
|
|
589
|
+
head :no_content
|
|
590
|
+
end
|
|
591
|
+
end
|
|
592
|
+
end
|
|
593
|
+
|
|
594
|
+
# Or just check the signature and timestamp
|
|
595
|
+
Twitch::EventsubWebhook.verify(secret: "...", headers: request.headers, body: request.raw_post)
|
|
596
|
+
|
|
597
|
+
# Allow a different maximum message age, in seconds (default 600)
|
|
598
|
+
Twitch::EventsubWebhook.new(secret: "...", headers: request.headers, body: request.raw_post, max_age: 300)
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
Other readers: `message_id`, `message_type`, `timestamp`, `retry?`, `subscription_version`, `payload` (the parsed body),
|
|
602
|
+
`signature_valid?`, and `expired?`.
|
|
603
|
+
|
|
440
604
|
### Custom Power-ups
|
|
441
605
|
|
|
442
606
|
```ruby
|
|
@@ -484,15 +648,13 @@ shards = [
|
|
|
484
648
|
}
|
|
485
649
|
}
|
|
486
650
|
]
|
|
487
|
-
@client.eventsub_conduits.update_shards(id: "abc123-def456", shards: shards)
|
|
488
|
-
```
|
|
651
|
+
result = @client.eventsub_conduits.update_shards(id: "abc123-def456", shards: shards)
|
|
489
652
|
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
@client.banned_events.list(broadcaster_id: 123)
|
|
653
|
+
# Twitch accepts up to 100 shards per request, so larger lists are sent in batches automatically.
|
|
654
|
+
# Twitch applies the valid shards even if others fail, so check errors for any that didn't update:
|
|
655
|
+
result.errors.each do |error|
|
|
656
|
+
puts "Shard #{error.id} failed: #{error.message} (#{error.code})"
|
|
657
|
+
end
|
|
496
658
|
```
|
|
497
659
|
|
|
498
660
|
### Banned Users
|
|
@@ -735,6 +897,11 @@ messages = [{msg_id: "abc1", msg_text: "is this allowed?"}, {msg_id: "abc2", msg
|
|
|
735
897
|
# Required scope: channel:read:charity
|
|
736
898
|
# broadcaster_id must match the currently authenticated user
|
|
737
899
|
@client.charity_campaigns.list broadcaster_id: 123
|
|
900
|
+
|
|
901
|
+
# Gets the donations made to the broadcaster's active charity campaign
|
|
902
|
+
# Required scope: channel:read:charity
|
|
903
|
+
# broadcaster_id must match the currently authenticated user
|
|
904
|
+
@client.charity_campaigns.donations(broadcaster_id: 123)
|
|
738
905
|
```
|
|
739
906
|
|
|
740
907
|
### Chatters
|
|
@@ -900,8 +1067,12 @@ outcomes = [
|
|
|
900
1067
|
# Check if a user is subscribed to a broadcaster
|
|
901
1068
|
# Required scope: user:read:subscriptions
|
|
902
1069
|
# user_id must match the currently authenticated user
|
|
1070
|
+
# Returns a collection with the subscription, or raises Twitch::Errors::EntityNotFoundError if not subscribed
|
|
903
1071
|
@client.subscriptions.is_subscribed(broadcaster_id: 123, user_id: 456)
|
|
904
1072
|
|
|
1073
|
+
# Or get true/false
|
|
1074
|
+
@client.subscriptions.subscribed?(broadcaster_id: 123, user_id: 456)
|
|
1075
|
+
|
|
905
1076
|
# Get subscription counts and points for a broadcaster
|
|
906
1077
|
# Required scope: channel:read:subscriptions
|
|
907
1078
|
# broadcaster_id must match the currently authenticated user
|
|
@@ -969,44 +1140,188 @@ outcomes = [
|
|
|
969
1140
|
@client.stream_markers.list(video_id: "video-id")
|
|
970
1141
|
```
|
|
971
1142
|
|
|
972
|
-
###
|
|
1143
|
+
### Hype Train Status
|
|
973
1144
|
|
|
974
1145
|
```ruby
|
|
975
|
-
# Get
|
|
976
|
-
|
|
1146
|
+
# Get hype train status for a broadcaster
|
|
1147
|
+
# Required scope: channel:read:hype_train
|
|
1148
|
+
# broadcaster_id must match the currently authenticated user
|
|
1149
|
+
@client.hype_train_status.retrieve(broadcaster_id: 123)
|
|
1150
|
+
```
|
|
977
1151
|
|
|
978
|
-
# Get stream tags for a specific broadcaster
|
|
979
|
-
@client.tags.stream(broadcaster_id: 123)
|
|
980
1152
|
|
|
981
|
-
|
|
982
|
-
|
|
1153
|
+
### Ads
|
|
1154
|
+
|
|
1155
|
+
```ruby
|
|
1156
|
+
# Gets the broadcaster's ad schedule and snooze details
|
|
1157
|
+
# Required scope: channel:read:ads
|
|
983
1158
|
# broadcaster_id must match the currently authenticated user
|
|
984
|
-
|
|
985
|
-
|
|
1159
|
+
@client.ads.schedule(broadcaster_id: 123)
|
|
1160
|
+
|
|
1161
|
+
# Pushes back the next scheduled ad by 5 minutes
|
|
1162
|
+
# Required scope: channel:manage:ads
|
|
1163
|
+
# broadcaster_id must match the currently authenticated user
|
|
1164
|
+
@client.ads.snooze(broadcaster_id: 123)
|
|
986
1165
|
```
|
|
987
1166
|
|
|
988
|
-
###
|
|
1167
|
+
### Analytics
|
|
989
1168
|
|
|
990
1169
|
```ruby
|
|
991
|
-
#
|
|
992
|
-
# Required scope:
|
|
993
|
-
#
|
|
994
|
-
@client.
|
|
1170
|
+
# Gets URLs for downloadable CSV reports about the authenticated user's extensions
|
|
1171
|
+
# Required scope: analytics:read:extensions
|
|
1172
|
+
# Available parameters: extension_id, type, started_at, ended_at, first, after
|
|
1173
|
+
@client.analytics.extensions(extension_id: "abc123")
|
|
1174
|
+
|
|
1175
|
+
# Gets URLs for downloadable CSV reports about the authenticated user's games
|
|
1176
|
+
# Required scope: analytics:read:games
|
|
1177
|
+
# Available parameters: game_id, type, started_at, ended_at, first, after
|
|
1178
|
+
@client.analytics.games(game_id: 123)
|
|
995
1179
|
```
|
|
996
1180
|
|
|
997
|
-
###
|
|
1181
|
+
### Bits
|
|
998
1182
|
|
|
999
1183
|
```ruby
|
|
1000
|
-
#
|
|
1001
|
-
# Required scope:
|
|
1002
|
-
#
|
|
1003
|
-
@client.
|
|
1184
|
+
# Gets the Bits leaderboard for the authenticated broadcaster
|
|
1185
|
+
# Required scope: bits:read
|
|
1186
|
+
# Available parameters: count, period, started_at, user_id
|
|
1187
|
+
@client.bits.leaderboard(count: 10, period: "week")
|
|
1188
|
+
|
|
1189
|
+
# Gets the global Cheermotes, plus a broadcaster's custom Cheermotes if broadcaster_id is given
|
|
1190
|
+
@client.bits.cheermotes
|
|
1191
|
+
@client.bits.cheermotes(broadcaster_id: 123)
|
|
1192
|
+
```
|
|
1193
|
+
|
|
1194
|
+
### Chat Settings
|
|
1195
|
+
|
|
1196
|
+
```ruby
|
|
1197
|
+
# Gets a broadcaster's chat settings
|
|
1198
|
+
# Pass moderator_id (matching the authenticated user) to include non_moderator_chat_delay settings
|
|
1199
|
+
@client.chat_settings.retrieve(broadcaster_id: 123)
|
|
1200
|
+
@client.chat_settings.retrieve(broadcaster_id: 123, moderator_id: 321)
|
|
1201
|
+
|
|
1202
|
+
# Updates a broadcaster's chat settings
|
|
1203
|
+
# Required scope: moderator:manage:chat_settings
|
|
1204
|
+
# moderator_id must match the currently authenticated user
|
|
1205
|
+
# Available attributes: emote_mode, follower_mode, follower_mode_duration, non_moderator_chat_delay,
|
|
1206
|
+
# non_moderator_chat_delay_duration, slow_mode, slow_mode_wait_time, subscriber_mode, unique_chat_mode
|
|
1207
|
+
@client.chat_settings.update(broadcaster_id: 123, moderator_id: 321, slow_mode: true, slow_mode_wait_time: 10)
|
|
1208
|
+
```
|
|
1209
|
+
|
|
1210
|
+
### Shield Mode
|
|
1211
|
+
|
|
1212
|
+
```ruby
|
|
1213
|
+
# Gets a broadcaster's Shield Mode status
|
|
1214
|
+
# Required scope: moderator:read:shield_mode or moderator:manage:shield_mode
|
|
1215
|
+
# moderator_id must match the currently authenticated user
|
|
1216
|
+
@client.shield_mode.retrieve(broadcaster_id: 123, moderator_id: 321)
|
|
1217
|
+
|
|
1218
|
+
# Turns Shield Mode on or off
|
|
1219
|
+
# Required scope: moderator:manage:shield_mode
|
|
1220
|
+
# moderator_id must match the currently authenticated user
|
|
1221
|
+
@client.shield_mode.update(broadcaster_id: 123, moderator_id: 321, is_active: true)
|
|
1222
|
+
```
|
|
1223
|
+
|
|
1224
|
+
### Content Classification Labels
|
|
1225
|
+
|
|
1226
|
+
```ruby
|
|
1227
|
+
# Gets the content classification labels that can be applied to a channel with channels.update
|
|
1228
|
+
@client.content_classification_labels.list
|
|
1229
|
+
@client.content_classification_labels.list(locale: "en-US")
|
|
1230
|
+
```
|
|
1231
|
+
|
|
1232
|
+
### Teams
|
|
1233
|
+
|
|
1234
|
+
```ruby
|
|
1235
|
+
# Gets a team by ID or name
|
|
1236
|
+
@client.teams.retrieve(id: 123)
|
|
1237
|
+
@client.teams.retrieve(name: "staff")
|
|
1238
|
+
|
|
1239
|
+
# Gets the teams a broadcaster is a member of
|
|
1240
|
+
@client.teams.channel(broadcaster_id: 123)
|
|
1241
|
+
```
|
|
1242
|
+
|
|
1243
|
+
### Drops Entitlements
|
|
1244
|
+
|
|
1245
|
+
```ruby
|
|
1246
|
+
# Gets Drops entitlements
|
|
1247
|
+
# The Client ID must be owned by a member of the organization that owns the game
|
|
1248
|
+
# Available parameters: id, user_id, game_id, fulfillment_status, first, after
|
|
1249
|
+
@client.drops_entitlements.list(user_id: 123)
|
|
1250
|
+
|
|
1251
|
+
# Updates the fulfillment status of Drops entitlements (CLAIMED or FULFILLED)
|
|
1252
|
+
@client.drops_entitlements.update(entitlement_ids: ["abc", "def"], fulfillment_status: "FULFILLED")
|
|
1253
|
+
```
|
|
1254
|
+
|
|
1255
|
+
### Extensions
|
|
1256
|
+
|
|
1257
|
+
Most Extensions endpoints require a signed JWT created by your Extension Backend Service rather than an
|
|
1258
|
+
OAuth token. Pass the JWT as the client's `access_token`. See
|
|
1259
|
+
[Signing the JWT](https://dev.twitch.tv/docs/extensions/building/#signing-the-jwt).
|
|
1260
|
+
|
|
1261
|
+
```ruby
|
|
1262
|
+
@ext_client = Twitch::Client.new(client_id: "extension-client-id", access_token: signed_jwt)
|
|
1263
|
+
|
|
1264
|
+
# Gets an extension (requires a JWT), or a released extension (app or user token)
|
|
1265
|
+
@ext_client.extensions.retrieve(extension_id: "abc123")
|
|
1266
|
+
@client.extensions.released(extension_id: "abc123", extension_version: "1.0.0")
|
|
1267
|
+
|
|
1268
|
+
# Gets live channels that have the extension installed or activated
|
|
1269
|
+
@client.extensions.live_channels(extension_id: "abc123")
|
|
1270
|
+
|
|
1271
|
+
# Gets and sets configuration segments (requires a JWT)
|
|
1272
|
+
# segment: broadcaster, developer or global. Pass an array to get more than one.
|
|
1273
|
+
@ext_client.extensions.configuration(extension_id: "abc123", segment: "broadcaster", broadcaster_id: 123)
|
|
1274
|
+
@ext_client.extensions.set_configuration(extension_id: "abc123", segment: "broadcaster", broadcaster_id: 123, content: "{}", version: "1")
|
|
1275
|
+
@ext_client.extensions.set_required_configuration(broadcaster_id: 123, extension_id: "abc123", extension_version: "1.0.0", required_configuration: "RCS")
|
|
1276
|
+
|
|
1277
|
+
# Sends a PubSub message or chat message (requires a JWT)
|
|
1278
|
+
@ext_client.extensions.send_pubsub_message(broadcaster_id: 123, target: ["broadcast"], message: "hello")
|
|
1279
|
+
@ext_client.extensions.send_chat_message(broadcaster_id: 123, text: "hello", extension_id: "abc123", extension_version: "1.0.0")
|
|
1280
|
+
|
|
1281
|
+
# Gets or creates the extension's JWT secrets (requires a JWT)
|
|
1282
|
+
@ext_client.extensions.secrets(extension_id: "abc123")
|
|
1283
|
+
@ext_client.extensions.create_secret(extension_id: "abc123", delay: 300)
|
|
1284
|
+
|
|
1285
|
+
# Gets and updates Bits products
|
|
1286
|
+
# Requires an app access token whose Client ID matches the extension's
|
|
1287
|
+
@app_client.extensions.bits_products(should_include_all: true)
|
|
1288
|
+
@app_client.extensions.update_bits_product(sku: "sku-1", cost: { amount: 100, type: "bits" }, display_name: "Thing")
|
|
1289
|
+
|
|
1290
|
+
# Gets Bits transactions for the extension
|
|
1291
|
+
# Requires an app access token
|
|
1292
|
+
@app_client.extensions.transactions(extension_id: "abc123")
|
|
1293
|
+
```
|
|
1294
|
+
|
|
1295
|
+
### Guest Star (Beta)
|
|
1296
|
+
|
|
1297
|
+
```ruby
|
|
1298
|
+
# Gets and updates a channel's Guest Star settings
|
|
1299
|
+
@client.guest_star.settings(broadcaster_id: 123, moderator_id: 321)
|
|
1300
|
+
@client.guest_star.update_settings(broadcaster_id: 123, slot_count: 4)
|
|
1301
|
+
|
|
1302
|
+
# Gets, creates and ends a Guest Star session
|
|
1303
|
+
@client.guest_star.session(broadcaster_id: 123, moderator_id: 321)
|
|
1304
|
+
@client.guest_star.create_session(broadcaster_id: 123)
|
|
1305
|
+
@client.guest_star.end_session(broadcaster_id: 123, session_id: "abc")
|
|
1306
|
+
|
|
1307
|
+
# Gets, sends and deletes invites
|
|
1308
|
+
@client.guest_star.invites(broadcaster_id: 123, moderator_id: 321, session_id: "abc")
|
|
1309
|
+
@client.guest_star.send_invite(broadcaster_id: 123, moderator_id: 321, session_id: "abc", guest_id: 456)
|
|
1310
|
+
@client.guest_star.delete_invite(broadcaster_id: 123, moderator_id: 321, session_id: "abc", guest_id: 456)
|
|
1311
|
+
|
|
1312
|
+
# Assigns, moves and removes guests in slots
|
|
1313
|
+
@client.guest_star.assign_slot(broadcaster_id: 123, moderator_id: 321, session_id: "abc", guest_id: 456, slot_id: "1")
|
|
1314
|
+
@client.guest_star.update_slot(broadcaster_id: 123, moderator_id: 321, session_id: "abc", source_slot_id: "1", destination_slot_id: "2")
|
|
1315
|
+
@client.guest_star.delete_slot(broadcaster_id: 123, moderator_id: 321, session_id: "abc", guest_id: 456, slot_id: "1")
|
|
1316
|
+
|
|
1317
|
+
# Updates a slot's audio, video, live and volume settings
|
|
1318
|
+
@client.guest_star.update_slot_settings(broadcaster_id: 123, moderator_id: 321, session_id: "abc", slot_id: "1", volume: 50)
|
|
1004
1319
|
```
|
|
1005
1320
|
|
|
1006
1321
|
|
|
1007
1322
|
## Contributing
|
|
1008
1323
|
|
|
1009
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
|
1324
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/d34ndev/twitchrb.
|
|
1010
1325
|
|
|
1011
1326
|
## License
|
|
1012
1327
|
|