twitchrb 1.10.0 → 1.11.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/CHANGELOG.md +24 -1
- data/Gemfile.lock +4 -4
- data/lib/twitch/collection.rb +4 -3
- data/lib/twitch/error_generator.rb +6 -4
- data/lib/twitch/oauth.rb +1 -3
- data/lib/twitch/resource.rb +20 -9
- data/lib/twitch/resources/announcements.rb +1 -1
- data/lib/twitch/resources/automod.rb +1 -1
- data/lib/twitch/resources/badges.rb +1 -1
- data/lib/twitch/resources/banned_users.rb +1 -1
- data/lib/twitch/resources/blocked_terms.rb +2 -2
- data/lib/twitch/resources/channels.rb +3 -3
- data/lib/twitch/resources/charity_campaigns.rb +1 -1
- data/lib/twitch/resources/chat_messages.rb +1 -1
- data/lib/twitch/resources/custom_reward_redemptions.rb +2 -2
- data/lib/twitch/resources/emotes.rb +2 -2
- data/lib/twitch/resources/eventsub_subscriptions.rb +8 -12
- data/lib/twitch/resources/games.rb +3 -5
- data/lib/twitch/resources/moderators.rb +1 -1
- data/lib/twitch/resources/raids.rb +1 -1
- data/lib/twitch/resources/shoutouts.rb +1 -1
- data/lib/twitch/resources/suspicious_users.rb +6 -2
- data/lib/twitch/resources/users.rb +12 -14
- data/lib/twitch/resources/videos.rb +1 -1
- data/lib/twitch/resources/vips.rb +1 -1
- data/lib/twitch/resources/warnings.rb +1 -1
- data/lib/twitch/version.rb +1 -1
- data/twitchrb.gemspec +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4a4de14d63208a337630d3530f24d90679645c2b4ad02d4f31beb96f687a6ff1
|
|
4
|
+
data.tar.gz: 2e49411b20156a55d93fa60e1dba87bf25121c228f601e10f6861e01aa9b0094
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 81bcbe6402c4cdf5f3cc90ac181aec22d8d46990053846f1bce3b92aead9f71462857c6b92e1b5dcbd4c34d1e635e057ce86516c856db1944252d01dc1e90b56
|
|
7
|
+
data.tar.gz: cfff782da54f1ffde515c8911febf8d251c1df677d0ba481399cfc86d2bd95c9885e0d5f6682aadbb96be98dc4cecf0ceda8aa72b073abdda842b4dc8e7ce120
|
data/.github/workflows/ci.yml
CHANGED
|
@@ -8,7 +8,7 @@ jobs:
|
|
|
8
8
|
continue-on-error: true
|
|
9
9
|
steps:
|
|
10
10
|
- name: Checkout code
|
|
11
|
-
uses: actions/checkout@
|
|
11
|
+
uses: actions/checkout@v7
|
|
12
12
|
- name: Set up Ruby
|
|
13
13
|
uses: ruby/setup-ruby@v1
|
|
14
14
|
with:
|
|
@@ -28,7 +28,7 @@ jobs:
|
|
|
28
28
|
- '3.4'
|
|
29
29
|
- '4.0'
|
|
30
30
|
steps:
|
|
31
|
-
- uses: actions/checkout@
|
|
31
|
+
- uses: actions/checkout@v7
|
|
32
32
|
- uses: ruby/setup-ruby@v1
|
|
33
33
|
with:
|
|
34
34
|
ruby-version: ${{ matrix.ruby_version }}
|
data/CHANGELOG.md
CHANGED
|
@@ -4,7 +4,30 @@ All notable changes to `twitchrb` are documented in this file.
|
|
|
4
4
|
|
|
5
5
|
Published release notes were sourced from GitHub releases where available. Older tag-only versions and the current unreleased work were reconstructed from local git history.
|
|
6
6
|
|
|
7
|
-
## [1.
|
|
7
|
+
## [1.11.0] - 2026-08-11
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
- Fixed a `NoMethodError` crash when API responses have non-JSON bodies, such as `stream_schedule.icalendar` (which was completely broken) and HTML error pages from proxies.
|
|
11
|
+
- Fixed `users.retrieve` and `games.retrieve` returning `nil` when a plural lookup (`ids`, `usernames`, `names`) matched exactly one item; plural lookups now always return a `Collection`. Singular lookups with no match now return `nil` instead of an empty object.
|
|
12
|
+
- Fixed `oauth.revoke` always returning `true`; it now returns `false` when revocation fails, matching `validate`, `create`, and `refresh`.
|
|
13
|
+
- Fixed `blocked_terms.create` returning a `BannedUser` instead of a `BlockedTerm`.
|
|
14
|
+
- Fixed `suspicious_users.delete` crashing on 204 No Content responses; it now returns `true`.
|
|
15
|
+
- Fixed query string values not being escaped in request paths. Notably, `users.update_color` silently dropped hex colors like `#9146FF`.
|
|
16
|
+
- Errors are now raised for any 4xx/5xx response; previously 422, 502, and 504 slipped through unraised.
|
|
17
|
+
- `Collection#total` now reports the `total` field from the API for paginated endpoints instead of the page size, and responses without a `data` key return an empty collection instead of raising.
|
|
18
|
+
- Removed a leftover debug `puts` in `users.get_color`.
|
|
19
|
+
- Error messages for unmapped statuses no longer duplicate the Twitch message.
|
|
20
|
+
- Updated the minimum Faraday version to 2.14.3 to fix the uncontrolled recursion denial-of-service vulnerability in `NestedParamsEncoder` (CVE-2026-54297).
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
- The `auto_retry_rate_limit` client option (default `true`) now works: requests that hit a 429 wait until the rate limit window resets and retry once. Previously the option was accepted but ignored.
|
|
24
|
+
- All API errors now inherit from `Twitch::Error`, so they can be rescued with a single base class.
|
|
25
|
+
- `eventsub_subscriptions.create` now goes through the shared request helpers, gaining request path validation and rate limit auto-retry.
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
- `users.get_color` accepts an array for `user_ids`, in line with other multi-id endpoints. Comma-separated strings still work.
|
|
29
|
+
|
|
30
|
+
## [1.10.0] - 2026-05-16
|
|
8
31
|
|
|
9
32
|
### Added
|
|
10
33
|
- Added custom power-up API support.
|
data/Gemfile.lock
CHANGED
|
@@ -2,7 +2,7 @@ PATH
|
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
4
|
twitchrb (1.10.0)
|
|
5
|
-
faraday (>= 2.14.
|
|
5
|
+
faraday (>= 2.14.3, < 3)
|
|
6
6
|
ostruct (~> 0.6.0)
|
|
7
7
|
|
|
8
8
|
GEM
|
|
@@ -27,7 +27,7 @@ GEM
|
|
|
27
27
|
benchmark (0.5.0)
|
|
28
28
|
bigdecimal (4.1.2)
|
|
29
29
|
cgi (0.5.1)
|
|
30
|
-
concurrent-ruby (1.3.
|
|
30
|
+
concurrent-ruby (1.3.8)
|
|
31
31
|
connection_pool (3.0.2)
|
|
32
32
|
crack (1.0.1)
|
|
33
33
|
bigdecimal
|
|
@@ -36,7 +36,7 @@ GEM
|
|
|
36
36
|
dotenv (3.2.0)
|
|
37
37
|
drb (2.2.3)
|
|
38
38
|
erb (6.0.4)
|
|
39
|
-
faraday (2.14.
|
|
39
|
+
faraday (2.14.3)
|
|
40
40
|
faraday-net_http (>= 2.0, < 3.5)
|
|
41
41
|
json
|
|
42
42
|
logger
|
|
@@ -51,7 +51,7 @@ GEM
|
|
|
51
51
|
prism (>= 1.3.0)
|
|
52
52
|
rdoc (>= 4.0.0)
|
|
53
53
|
reline (>= 0.4.2)
|
|
54
|
-
json (2.
|
|
54
|
+
json (2.21.2)
|
|
55
55
|
language_server-protocol (3.17.0.5)
|
|
56
56
|
lint_roller (1.1.0)
|
|
57
57
|
logger (1.7.0)
|
data/lib/twitch/collection.rb
CHANGED
|
@@ -6,10 +6,11 @@ module Twitch
|
|
|
6
6
|
|
|
7
7
|
def self.from_response(response, type:)
|
|
8
8
|
body = response.body
|
|
9
|
+
data = body["data"] || []
|
|
9
10
|
|
|
10
11
|
new(
|
|
11
|
-
data:
|
|
12
|
-
total: body["
|
|
12
|
+
data: data.map { |attrs| type.new(attrs) },
|
|
13
|
+
total: body["total"] || data.count,
|
|
13
14
|
cursor: body.dig("pagination", "cursor")
|
|
14
15
|
)
|
|
15
16
|
end
|
|
@@ -17,7 +18,7 @@ module Twitch
|
|
|
17
18
|
def initialize(data:, total:, cursor:)
|
|
18
19
|
@data = data
|
|
19
20
|
@total = total
|
|
20
|
-
@cursor = cursor
|
|
21
|
+
@cursor = cursor
|
|
21
22
|
end
|
|
22
23
|
|
|
23
24
|
def each(&block)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
module Twitch
|
|
2
|
-
class ErrorGenerator <
|
|
2
|
+
class ErrorGenerator < Error
|
|
3
|
+
attr_reader :response_body
|
|
3
4
|
attr_reader :http_status_code
|
|
4
5
|
attr_reader :twitch_error_code
|
|
5
6
|
attr_reader :twitch_error_message
|
|
@@ -40,10 +41,11 @@ module Twitch
|
|
|
40
41
|
end
|
|
41
42
|
|
|
42
43
|
def build_message
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
message = "Error #{@http_status_code}: #{error_message}"
|
|
45
|
+
if twitch_error_message && twitch_error_message != error_message
|
|
46
|
+
message += " '#{twitch_error_message}'"
|
|
45
47
|
end
|
|
46
|
-
|
|
48
|
+
message
|
|
47
49
|
end
|
|
48
50
|
end
|
|
49
51
|
|
data/lib/twitch/oauth.rb
CHANGED
data/lib/twitch/resource.rb
CHANGED
|
@@ -10,27 +10,40 @@ module Twitch
|
|
|
10
10
|
|
|
11
11
|
def get_request(url, params: {}, headers: {})
|
|
12
12
|
validate_request_path!(url)
|
|
13
|
-
|
|
13
|
+
execute_request { client.connection.get(url, params, headers) }
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def post_request(url, body:, headers: {})
|
|
17
17
|
validate_request_path!(url)
|
|
18
|
-
|
|
18
|
+
execute_request { client.connection.post(url, body, headers) }
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def patch_request(url, body:, headers: {})
|
|
22
22
|
validate_request_path!(url)
|
|
23
|
-
|
|
23
|
+
execute_request { client.connection.patch(url, body, headers) }
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
def put_request(url, body:, headers: {})
|
|
27
27
|
validate_request_path!(url)
|
|
28
|
-
|
|
28
|
+
execute_request { client.connection.put(url, body, headers) }
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
def delete_request(url, params: {}, headers: {})
|
|
32
32
|
validate_request_path!(url)
|
|
33
|
-
|
|
33
|
+
execute_request { client.connection.delete(url, params, headers) }
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def execute_request
|
|
37
|
+
response = yield
|
|
38
|
+
|
|
39
|
+
# Retry once after a 429, waiting until the rate limit window resets
|
|
40
|
+
if response.status == 429 && client.auto_retry_rate_limit
|
|
41
|
+
update_rate_limit(response)
|
|
42
|
+
client.rate_limiter.wait_if_rate_limited
|
|
43
|
+
response = yield
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
handle_response(response)
|
|
34
47
|
end
|
|
35
48
|
|
|
36
49
|
def handle_response(response)
|
|
@@ -44,8 +57,8 @@ module Twitch
|
|
|
44
57
|
end
|
|
45
58
|
|
|
46
59
|
def error?(response)
|
|
47
|
-
|
|
48
|
-
response.body
|
|
60
|
+
response.status >= 400 ||
|
|
61
|
+
(response.body.is_a?(Hash) && response.body.key?("error"))
|
|
49
62
|
end
|
|
50
63
|
|
|
51
64
|
def raise_error(response)
|
|
@@ -58,8 +71,6 @@ module Twitch
|
|
|
58
71
|
raise error if error
|
|
59
72
|
end
|
|
60
73
|
|
|
61
|
-
private
|
|
62
|
-
|
|
63
74
|
def update_rate_limit(response)
|
|
64
75
|
client.rate_limiter.update(response.headers)
|
|
65
76
|
client.rate_limiter.warn_if_approaching(threshold: client.rate_limit_threshold)
|
|
@@ -5,7 +5,7 @@ module Twitch
|
|
|
5
5
|
def create(broadcaster_id:, moderator_id:, message:, color: nil, for_source_only: nil)
|
|
6
6
|
attrs = { message: message, color: color, for_source_only: for_source_only }
|
|
7
7
|
|
|
8
|
-
post_request("chat/announcements
|
|
8
|
+
post_request("chat/announcements?#{URI.encode_www_form(broadcaster_id: broadcaster_id, moderator_id: moderator_id)}", body: attrs)
|
|
9
9
|
end
|
|
10
10
|
end
|
|
11
11
|
end
|
|
@@ -22,7 +22,7 @@ module Twitch
|
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
def settings(broadcaster_id:, moderator_id:)
|
|
25
|
-
response = get_request("moderation/automod/settings
|
|
25
|
+
response = get_request("moderation/automod/settings", params: { broadcaster_id: broadcaster_id, moderator_id: moderator_id })
|
|
26
26
|
AutomodSetting.new response.body.dig("data")[0]
|
|
27
27
|
end
|
|
28
28
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module Twitch
|
|
2
2
|
class BadgesResource < Resource
|
|
3
3
|
def channel(broadcaster_id:)
|
|
4
|
-
response = get_request("chat/badges
|
|
4
|
+
response = get_request("chat/badges", params: { broadcaster_id: broadcaster_id })
|
|
5
5
|
Collection.from_response(response, type: Badge)
|
|
6
6
|
end
|
|
7
7
|
|
|
@@ -17,7 +17,7 @@ module Twitch
|
|
|
17
17
|
# Required scope: moderator:manage:banned_users
|
|
18
18
|
# moderator_id must match the currently authenticated user. Can be either the broadcaster ID or moderator ID
|
|
19
19
|
def delete(broadcaster_id:, moderator_id:, user_id:)
|
|
20
|
-
delete_request("moderation/bans
|
|
20
|
+
delete_request("moderation/bans", params: { broadcaster_id: broadcaster_id, moderator_id: moderator_id, user_id: user_id })
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
23
|
end
|
|
@@ -13,13 +13,13 @@ module Twitch
|
|
|
13
13
|
def create(broadcaster_id:, moderator_id:, text:)
|
|
14
14
|
attrs = { broadcaster_id: broadcaster_id, moderator_id: moderator_id, text: text }
|
|
15
15
|
response = post_request("moderation/blocked_terms", body: attrs)
|
|
16
|
-
|
|
16
|
+
BlockedTerm.new response.body.dig("data")[0]
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
# Required scope: moderator:manage:blocked_terms
|
|
20
20
|
# moderator_id must match the currently authenticated user. Can be either the broadcaster ID or moderator ID
|
|
21
21
|
def delete(broadcaster_id:, moderator_id:, id:)
|
|
22
|
-
delete_request("moderation/blocked_terms
|
|
22
|
+
delete_request("moderation/blocked_terms", params: { broadcaster_id: broadcaster_id, moderator_id: moderator_id, id: id })
|
|
23
23
|
end
|
|
24
24
|
end
|
|
25
25
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module Twitch
|
|
2
2
|
class ChannelsResource < Resource
|
|
3
3
|
def retrieve(id:)
|
|
4
|
-
Channel.new get_request("channels
|
|
4
|
+
Channel.new get_request("channels", params: { broadcaster_id: id }).body.dig("data")[0]
|
|
5
5
|
end
|
|
6
6
|
|
|
7
7
|
# Retrieve a list of broadcasters a specified user follows
|
|
@@ -42,12 +42,12 @@ module Twitch
|
|
|
42
42
|
|
|
43
43
|
# Requires scope: channel:read:editors
|
|
44
44
|
def editors(broadcaster_id:)
|
|
45
|
-
response = get_request("channels/editors
|
|
45
|
+
response = get_request("channels/editors", params: { broadcaster_id: broadcaster_id })
|
|
46
46
|
Collection.from_response(response, type: ChannelEditor)
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
def stream_key(broadcaster_id:)
|
|
50
|
-
response = get_request("streams/key
|
|
50
|
+
response = get_request("streams/key", params: { broadcaster_id: broadcaster_id })
|
|
51
51
|
StreamKey.new(response.body.dig("data")[0])
|
|
52
52
|
end
|
|
53
53
|
|
|
@@ -3,7 +3,7 @@ module Twitch
|
|
|
3
3
|
# Required scope: channel:read:charity
|
|
4
4
|
# Broadcaster ID must match the user in the OAuth token
|
|
5
5
|
def list(broadcaster_id:)
|
|
6
|
-
response = get_request("charity/campaigns
|
|
6
|
+
response = get_request("charity/campaigns", params: { broadcaster_id: broadcaster_id })
|
|
7
7
|
if response.body.dig("data")[0]
|
|
8
8
|
CharityCampaign.new(response.body.dig("data")[0])
|
|
9
9
|
else
|
|
@@ -16,7 +16,7 @@ module Twitch
|
|
|
16
16
|
|
|
17
17
|
# moderator_id must match the user in the OAuth token
|
|
18
18
|
def delete(broadcaster_id:, moderator_id:, message_id:)
|
|
19
|
-
delete_request("moderation/chat
|
|
19
|
+
delete_request("moderation/chat", params: { broadcaster_id: broadcaster_id, moderator_id: moderator_id, message_id: message_id })
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
end
|
|
@@ -12,8 +12,8 @@ module Twitch
|
|
|
12
12
|
# Broadcaster ID must match the user in the OAuth token
|
|
13
13
|
def update(broadcaster_id:, reward_id:, redemption_id:, status:)
|
|
14
14
|
attributes = { status: status.upcase }
|
|
15
|
-
|
|
16
|
-
response = patch_request(
|
|
15
|
+
query = URI.encode_www_form(broadcaster_id: broadcaster_id, reward_id: reward_id, id: redemption_id, status: status.upcase)
|
|
16
|
+
response = patch_request("channel_points/custom_rewards/redemptions?#{query}", body: attributes)
|
|
17
17
|
|
|
18
18
|
CustomRewardRedemption.new(response.body.dig("data")[0]) if response.success?
|
|
19
19
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module Twitch
|
|
2
2
|
class EmotesResource < Resource
|
|
3
3
|
def channel(broadcaster_id:)
|
|
4
|
-
response = get_request("chat/emotes
|
|
4
|
+
response = get_request("chat/emotes", params: { broadcaster_id: broadcaster_id })
|
|
5
5
|
Collection.from_response(response, type: Emote)
|
|
6
6
|
end
|
|
7
7
|
|
|
@@ -11,7 +11,7 @@ module Twitch
|
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def sets(emote_set_id:)
|
|
14
|
-
response = get_request("chat/emotes/set
|
|
14
|
+
response = get_request("chat/emotes/set", params: { emote_set_id: emote_set_id })
|
|
15
15
|
Collection.from_response(response, type: Emote)
|
|
16
16
|
end
|
|
17
17
|
end
|
|
@@ -7,20 +7,16 @@ module Twitch
|
|
|
7
7
|
|
|
8
8
|
def create(type:, version:, condition:, transport:, **params)
|
|
9
9
|
attributes = { type: type, version: version, condition: condition, transport: transport }.merge(params)
|
|
10
|
-
response =
|
|
11
|
-
update_rate_limit(response)
|
|
12
|
-
|
|
13
|
-
if response.status == 409
|
|
14
|
-
raise Twitch::Errors::EventsubSubscriptionConflictError.new(
|
|
15
|
-
response.body,
|
|
16
|
-
response.status,
|
|
17
|
-
existing_subscription_id: response.body.dig("data", 0, "id")
|
|
18
|
-
)
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
return raise_error(response) if error?(response)
|
|
10
|
+
response = post_request("eventsub/subscriptions", body: attributes)
|
|
22
11
|
|
|
23
12
|
EventsubSubscription.new(response.body.dig("data")[0]) if response.success?
|
|
13
|
+
rescue Twitch::Errors::ConflictError => error
|
|
14
|
+
existing_id = error.response_body.dig("data", 0, "id") if error.response_body.is_a?(Hash)
|
|
15
|
+
raise Twitch::Errors::EventsubSubscriptionConflictError.new(
|
|
16
|
+
error.response_body,
|
|
17
|
+
error.http_status_code,
|
|
18
|
+
existing_subscription_id: existing_id
|
|
19
|
+
)
|
|
24
20
|
end
|
|
25
21
|
|
|
26
22
|
def delete(id:)
|
|
@@ -14,12 +14,10 @@ module Twitch
|
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
body = response.body.dig("data")
|
|
17
|
-
if id || name
|
|
18
|
-
Game.new
|
|
19
|
-
elsif ids || names && body.count > 1
|
|
20
|
-
Collection.from_response(response, type: Game)
|
|
17
|
+
if id || name
|
|
18
|
+
body.empty? ? nil : Game.new(body[0])
|
|
21
19
|
else
|
|
22
|
-
|
|
20
|
+
Collection.from_response(response, type: Game)
|
|
23
21
|
end
|
|
24
22
|
end
|
|
25
23
|
|
|
@@ -17,7 +17,7 @@ module Twitch
|
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def delete(broadcaster_id:, user_id:)
|
|
20
|
-
delete_request("moderation/moderators
|
|
20
|
+
delete_request("moderation/moderators", params: { broadcaster_id: broadcaster_id, user_id: user_id })
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
23
|
end
|
|
@@ -5,7 +5,7 @@ module Twitch
|
|
|
5
5
|
# To: the ID of the Broadcaster the Shoutout will be for
|
|
6
6
|
# Required scope: moderator:manage:shoutouts
|
|
7
7
|
def create(from:, to:, moderator_id:)
|
|
8
|
-
post_request("chat/shoutouts
|
|
8
|
+
post_request("chat/shoutouts?#{URI.encode_www_form(from_broadcaster_id: from, to_broadcaster_id: to, moderator_id: moderator_id)}", body: nil)
|
|
9
9
|
end
|
|
10
10
|
end
|
|
11
11
|
end
|
|
@@ -5,7 +5,7 @@ module Twitch
|
|
|
5
5
|
def create(broadcaster_id:, moderator_id:, user_id:, status:)
|
|
6
6
|
attrs = { user_id: user_id, status: status }
|
|
7
7
|
response = post_request(
|
|
8
|
-
"moderation/suspicious_users
|
|
8
|
+
"moderation/suspicious_users?#{URI.encode_www_form(broadcaster_id: broadcaster_id, moderator_id: moderator_id)}",
|
|
9
9
|
body: attrs
|
|
10
10
|
)
|
|
11
11
|
|
|
@@ -16,9 +16,13 @@ module Twitch
|
|
|
16
16
|
# moderator_id must match the currently authenticated moderator
|
|
17
17
|
def delete(broadcaster_id:, moderator_id:, user_id:)
|
|
18
18
|
response = delete_request(
|
|
19
|
-
"moderation/suspicious_users
|
|
19
|
+
"moderation/suspicious_users",
|
|
20
|
+
params: { broadcaster_id: broadcaster_id, moderator_id: moderator_id, user_id: user_id }
|
|
20
21
|
)
|
|
21
22
|
|
|
23
|
+
# delete_request returns true for 204 No Content responses
|
|
24
|
+
return true unless response.respond_to?(:body)
|
|
25
|
+
|
|
22
26
|
SuspiciousUser.new(response.body.dig("data")[0])
|
|
23
27
|
end
|
|
24
28
|
end
|
|
@@ -14,12 +14,10 @@ module Twitch
|
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
body = response.body.dig("data")
|
|
17
|
-
if id || username
|
|
18
|
-
User.new
|
|
19
|
-
elsif ids || usernames && body.count > 1
|
|
20
|
-
Collection.from_response(response, type: User)
|
|
17
|
+
if id || username
|
|
18
|
+
body.empty? ? nil : User.new(body[0])
|
|
21
19
|
else
|
|
22
|
-
|
|
20
|
+
Collection.from_response(response, type: User)
|
|
23
21
|
end
|
|
24
22
|
end
|
|
25
23
|
|
|
@@ -31,13 +29,13 @@ module Twitch
|
|
|
31
29
|
end
|
|
32
30
|
|
|
33
31
|
def get_color(user_id: nil, user_ids: nil)
|
|
34
|
-
if user_ids
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
response = get_request("chat/color?#{
|
|
32
|
+
if user_ids
|
|
33
|
+
ids = user_ids.is_a?(Array) ? user_ids : user_ids.split(",")
|
|
34
|
+
query = URI.encode_www_form(ids.map { |i| [ "user_id", i.to_s.strip ] })
|
|
35
|
+
response = get_request("chat/color?#{query}")
|
|
38
36
|
Collection.from_response(response, type: UserColor)
|
|
39
37
|
else
|
|
40
|
-
response = get_request("chat/color
|
|
38
|
+
response = get_request("chat/color", params: { user_id: user_id })
|
|
41
39
|
UserColor.new response.body.dig("data")[0]
|
|
42
40
|
end
|
|
43
41
|
end
|
|
@@ -46,7 +44,7 @@ module Twitch
|
|
|
46
44
|
# Required scope: user:manage:chat_color
|
|
47
45
|
# user_id must be the currently authenticated user
|
|
48
46
|
def update_color(user_id:, color:)
|
|
49
|
-
put_request("chat/color
|
|
47
|
+
put_request("chat/color?#{URI.encode_www_form(user_id: user_id, color: color)}", body: {})
|
|
50
48
|
end
|
|
51
49
|
|
|
52
50
|
# Deprecated.
|
|
@@ -61,18 +59,18 @@ module Twitch
|
|
|
61
59
|
|
|
62
60
|
# Required scope: user:read:blocked_users
|
|
63
61
|
def blocks(broadcaster_id:, **params)
|
|
64
|
-
response = get_request("users/blocks
|
|
62
|
+
response = get_request("users/blocks", params: params.merge(broadcaster_id: broadcaster_id))
|
|
65
63
|
Collection.from_response(response, type: BlockedUser)
|
|
66
64
|
end
|
|
67
65
|
|
|
68
66
|
# Required scope: user:manage:blocked_users
|
|
69
67
|
def block_user(target_user_id:, **attributes)
|
|
70
|
-
put_request("users/blocks
|
|
68
|
+
put_request("users/blocks?#{URI.encode_www_form(target_user_id: target_user_id)}", body: attributes)
|
|
71
69
|
end
|
|
72
70
|
|
|
73
71
|
# Required scope: user:manage:blocked_users
|
|
74
72
|
def unblock_user(target_user_id:)
|
|
75
|
-
delete_request("users/blocks
|
|
73
|
+
delete_request("users/blocks", params: { target_user_id: target_user_id })
|
|
76
74
|
end
|
|
77
75
|
|
|
78
76
|
# A quick method to see if a user is following a channel
|
|
@@ -11,7 +11,7 @@ module Twitch
|
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def delete(broadcaster_id:, user_id:)
|
|
14
|
-
delete_request("channels/vips
|
|
14
|
+
delete_request("channels/vips", params: { broadcaster_id: broadcaster_id, user_id: user_id })
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
end
|
|
@@ -5,7 +5,7 @@ module Twitch
|
|
|
5
5
|
def create(broadcaster_id:, moderator_id:, user_id:, reason:)
|
|
6
6
|
attrs = { user_id: user_id, reason: reason }
|
|
7
7
|
|
|
8
|
-
response = post_request("moderation/warnings
|
|
8
|
+
response = post_request("moderation/warnings?#{URI.encode_www_form(broadcaster_id: broadcaster_id, moderator_id: moderator_id)}", body: { data: attrs })
|
|
9
9
|
Collection.from_response(response, type: Warning)
|
|
10
10
|
end
|
|
11
11
|
end
|
data/lib/twitch/version.rb
CHANGED
data/twitchrb.gemspec
CHANGED
|
@@ -24,6 +24,6 @@ Gem::Specification.new do |spec|
|
|
|
24
24
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
25
25
|
spec.require_paths = [ "lib" ]
|
|
26
26
|
|
|
27
|
-
spec.add_dependency "faraday", ">= 2.14.
|
|
27
|
+
spec.add_dependency "faraday", ">= 2.14.3", "< 3"
|
|
28
28
|
spec.add_dependency "ostruct", "~> 0.6.0"
|
|
29
29
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: twitchrb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.11.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dean Perry
|
|
@@ -15,7 +15,7 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - ">="
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 2.14.
|
|
18
|
+
version: 2.14.3
|
|
19
19
|
- - "<"
|
|
20
20
|
- !ruby/object:Gem::Version
|
|
21
21
|
version: '3'
|
|
@@ -25,7 +25,7 @@ dependencies:
|
|
|
25
25
|
requirements:
|
|
26
26
|
- - ">="
|
|
27
27
|
- !ruby/object:Gem::Version
|
|
28
|
-
version: 2.14.
|
|
28
|
+
version: 2.14.3
|
|
29
29
|
- - "<"
|
|
30
30
|
- !ruby/object:Gem::Version
|
|
31
31
|
version: '3'
|
|
@@ -190,7 +190,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
190
190
|
- !ruby/object:Gem::Version
|
|
191
191
|
version: '0'
|
|
192
192
|
requirements: []
|
|
193
|
-
rubygems_version: 4.0.
|
|
193
|
+
rubygems_version: 4.0.16
|
|
194
194
|
specification_version: 4
|
|
195
195
|
summary: A Ruby library for interacting with the Twitch Helix API
|
|
196
196
|
test_files: []
|