twitchrb 1.3.0 → 1.5.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/dependabot.yml +11 -0
- data/.github/workflows/ci.yml +11 -5
- data/.rubocop.yml +3 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +67 -57
- data/README.md +216 -0
- data/lib/twitch/error_generator.rb +128 -0
- data/lib/twitch/resource.rb +14 -25
- data/lib/twitch/version.rb +1 -1
- data/lib/twitch.rb +6 -1
- data/mise.toml +2 -0
- data/twitchrb.gemspec +2 -1
- metadata +22 -10
- data/lib/twitch/resources/event_sub_conduit.rb +0 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 901a6fa2ce68163b04be8e9ac4827311ba51ebbf10ebd1b2ac22431093200625
|
4
|
+
data.tar.gz: d72fb9133fa476489a4378abceec8e4b8456394bf0706dbb02a3f1a97c2a4ad5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6cc69cb4c54daa8ceb639c0e2c73541b2f6091ba43b94bad887858d178bb9a259b3095fb243d95428224ea855bdaf92a3f36381aa908883882ce002638f9187b
|
7
|
+
data.tar.gz: 486829ca4f786fbdb4141ff8ae5da79420f6438a1af959f8604818e0a29778e62ec2fcc452868046739bbb37a45649ae8eadd1995213537edef49da339511ddc
|
data/.github/workflows/ci.yml
CHANGED
@@ -1,15 +1,21 @@
|
|
1
1
|
name: CI
|
2
|
-
on:
|
2
|
+
on:
|
3
|
+
push:
|
4
|
+
branches:
|
5
|
+
- main
|
6
|
+
pull_request:
|
7
|
+
branches:
|
8
|
+
- main
|
3
9
|
jobs:
|
4
10
|
lint:
|
5
11
|
runs-on: ubuntu-latest
|
6
12
|
steps:
|
7
13
|
- name: Checkout code
|
8
|
-
uses: actions/checkout@
|
14
|
+
uses: actions/checkout@v5
|
9
15
|
- name: Set up Ruby
|
10
16
|
uses: ruby/setup-ruby@v1
|
11
17
|
with:
|
12
|
-
ruby-version: '3.
|
18
|
+
ruby-version: '3.4'
|
13
19
|
bundler-cache: true
|
14
20
|
- name: Lint code for consistent style
|
15
21
|
run: bundle exec rubocop -f github
|
@@ -21,11 +27,11 @@ jobs:
|
|
21
27
|
fail-fast: false
|
22
28
|
matrix:
|
23
29
|
ruby_version:
|
24
|
-
- '3.1'
|
25
30
|
- '3.2'
|
26
31
|
- '3.3'
|
32
|
+
- '3.4'
|
27
33
|
steps:
|
28
|
-
- uses: actions/checkout@
|
34
|
+
- uses: actions/checkout@v5
|
29
35
|
- uses: ruby/setup-ruby@v1
|
30
36
|
with:
|
31
37
|
ruby-version: ${{ matrix.ruby_version }}
|
data/.rubocop.yml
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,93 +1,103 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
twitchrb (1.
|
5
|
-
faraday (~> 2.
|
4
|
+
twitchrb (1.5.0)
|
5
|
+
faraday (~> 2.11)
|
6
|
+
ostruct (~> 0.6.0)
|
6
7
|
|
7
8
|
GEM
|
8
9
|
remote: https://rubygems.org/
|
9
10
|
specs:
|
10
|
-
activesupport (7.
|
11
|
+
activesupport (7.2.2.2)
|
11
12
|
base64
|
13
|
+
benchmark (>= 0.3)
|
12
14
|
bigdecimal
|
13
|
-
concurrent-ruby (~> 1.0, >= 1.
|
15
|
+
concurrent-ruby (~> 1.0, >= 1.3.1)
|
14
16
|
connection_pool (>= 2.2.5)
|
15
17
|
drb
|
16
18
|
i18n (>= 1.6, < 2)
|
19
|
+
logger (>= 1.4.2)
|
17
20
|
minitest (>= 5.1)
|
18
|
-
|
19
|
-
tzinfo (~> 2.0)
|
20
|
-
ast (2.4.
|
21
|
-
base64 (0.
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
21
|
+
securerandom (>= 0.3)
|
22
|
+
tzinfo (~> 2.0, >= 2.0.5)
|
23
|
+
ast (2.4.3)
|
24
|
+
base64 (0.3.0)
|
25
|
+
benchmark (0.4.1)
|
26
|
+
bigdecimal (3.2.3)
|
27
|
+
concurrent-ruby (1.3.5)
|
28
|
+
connection_pool (2.5.4)
|
29
|
+
dotenv (3.1.8)
|
30
|
+
drb (2.2.3)
|
31
|
+
faraday (2.13.4)
|
32
|
+
faraday-net_http (>= 2.0, < 3.5)
|
33
|
+
json
|
34
|
+
logger
|
35
|
+
faraday-net_http (3.4.1)
|
36
|
+
net-http (>= 0.5.0)
|
37
|
+
i18n (1.14.7)
|
32
38
|
concurrent-ruby (~> 1.0)
|
33
|
-
json (2.
|
34
|
-
language_server-protocol (3.17.0.
|
35
|
-
|
36
|
-
|
37
|
-
|
39
|
+
json (2.13.2)
|
40
|
+
language_server-protocol (3.17.0.5)
|
41
|
+
lint_roller (1.1.0)
|
42
|
+
logger (1.7.0)
|
43
|
+
minitest (5.25.5)
|
44
|
+
net-http (0.6.0)
|
38
45
|
uri
|
39
|
-
|
40
|
-
|
46
|
+
ostruct (0.6.3)
|
47
|
+
parallel (1.27.0)
|
48
|
+
parser (3.3.9.0)
|
41
49
|
ast (~> 2.4.1)
|
42
50
|
racc
|
43
|
-
|
44
|
-
|
51
|
+
prism (1.5.0)
|
52
|
+
racc (1.8.1)
|
53
|
+
rack (3.2.1)
|
45
54
|
rainbow (3.1.1)
|
46
55
|
rake (12.3.3)
|
47
|
-
regexp_parser (2.
|
48
|
-
|
49
|
-
strscan
|
50
|
-
rubocop (1.64.1)
|
56
|
+
regexp_parser (2.11.2)
|
57
|
+
rubocop (1.80.2)
|
51
58
|
json (~> 2.3)
|
52
|
-
language_server-protocol (
|
59
|
+
language_server-protocol (~> 3.17.0.2)
|
60
|
+
lint_roller (~> 1.1.0)
|
53
61
|
parallel (~> 1.10)
|
54
62
|
parser (>= 3.3.0.2)
|
55
63
|
rainbow (>= 2.2.2, < 4.0)
|
56
|
-
regexp_parser (>=
|
57
|
-
|
58
|
-
rubocop-ast (>= 1.31.1, < 2.0)
|
64
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
65
|
+
rubocop-ast (>= 1.46.0, < 2.0)
|
59
66
|
ruby-progressbar (~> 1.7)
|
60
|
-
unicode-display_width (>= 2.4.0, <
|
61
|
-
rubocop-ast (1.
|
62
|
-
parser (>= 3.3.
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
rubocop (>= 1.
|
68
|
-
|
69
|
-
rubocop-rails (2.25.0)
|
67
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
68
|
+
rubocop-ast (1.46.0)
|
69
|
+
parser (>= 3.3.7.2)
|
70
|
+
prism (~> 1.4)
|
71
|
+
rubocop-performance (1.26.0)
|
72
|
+
lint_roller (~> 1.1)
|
73
|
+
rubocop (>= 1.75.0, < 2.0)
|
74
|
+
rubocop-ast (>= 1.44.0, < 2.0)
|
75
|
+
rubocop-rails (2.33.3)
|
70
76
|
activesupport (>= 4.2.0)
|
77
|
+
lint_roller (~> 1.1)
|
71
78
|
rack (>= 1.1)
|
72
|
-
rubocop (>= 1.
|
73
|
-
rubocop-ast (>= 1.
|
74
|
-
rubocop-rails-omakase (1.
|
75
|
-
rubocop
|
76
|
-
rubocop-
|
77
|
-
rubocop-
|
78
|
-
rubocop-rails
|
79
|
+
rubocop (>= 1.75.0, < 2.0)
|
80
|
+
rubocop-ast (>= 1.44.0, < 2.0)
|
81
|
+
rubocop-rails-omakase (1.1.0)
|
82
|
+
rubocop (>= 1.72)
|
83
|
+
rubocop-performance (>= 1.24)
|
84
|
+
rubocop-rails (>= 2.30)
|
79
85
|
ruby-progressbar (1.13.0)
|
80
|
-
|
86
|
+
securerandom (0.4.1)
|
81
87
|
tzinfo (2.0.6)
|
82
88
|
concurrent-ruby (~> 1.0)
|
83
|
-
unicode-display_width (2.
|
84
|
-
|
85
|
-
|
89
|
+
unicode-display_width (3.2.0)
|
90
|
+
unicode-emoji (~> 4.1)
|
91
|
+
unicode-emoji (4.1.0)
|
92
|
+
uri (1.0.3)
|
93
|
+
vcr (6.3.1)
|
94
|
+
base64
|
86
95
|
|
87
96
|
PLATFORMS
|
88
97
|
ruby
|
89
98
|
|
90
99
|
DEPENDENCIES
|
100
|
+
activesupport (>= 4.2.0, < 8.0)
|
91
101
|
dotenv
|
92
102
|
minitest (~> 5.0)
|
93
103
|
rake (~> 12.0)
|
@@ -96,4 +106,4 @@ DEPENDENCIES
|
|
96
106
|
vcr
|
97
107
|
|
98
108
|
BUNDLED WITH
|
99
|
-
2.
|
109
|
+
2.5.17
|
data/README.md
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
# TwitchRB
|
2
2
|
|
3
|
+
[](https://github.com/deanpcmad/twitchrb/actions/workflows/ci.yml)
|
4
|
+
[](https://badge.fury.io/rb/twitchrb)
|
5
|
+
[](https://rubygems.org/gems/twitchrb)
|
6
|
+
|
3
7
|
TwitchRB is the easiest and most complete Ruby library for the [Twitch Helix API](https://dev.twitch.tv/docs/api).
|
4
8
|
|
5
9
|
## Installation
|
@@ -275,6 +279,44 @@ These require an application OAuth access token.
|
|
275
279
|
@client.eventsub_subscriptions.delete(id: "abc12-abc12-abc12")
|
276
280
|
```
|
277
281
|
|
282
|
+
### EventSub Conduits
|
283
|
+
|
284
|
+
Conduits provide a way to receive events over multiple transports. These require an application OAuth access token.
|
285
|
+
|
286
|
+
```ruby
|
287
|
+
# List all conduits for your application
|
288
|
+
@client.eventsub_conduits.list
|
289
|
+
|
290
|
+
# Create a conduit with a specified number of shards
|
291
|
+
# shard_count must be between 1 and 100
|
292
|
+
@client.eventsub_conduits.create(shard_count: 10)
|
293
|
+
|
294
|
+
# Update a conduit's shard count
|
295
|
+
@client.eventsub_conduits.update(id: "abc123-def456", shard_count: 20)
|
296
|
+
|
297
|
+
# Delete a conduit
|
298
|
+
@client.eventsub_conduits.delete(id: "abc123-def456")
|
299
|
+
|
300
|
+
# List shards for a conduit
|
301
|
+
# Optional parameters: status, after
|
302
|
+
@client.eventsub_conduits.shards(id: "abc123-def456")
|
303
|
+
@client.eventsub_conduits.shards(id: "abc123-def456", status: "enabled")
|
304
|
+
|
305
|
+
# Update shards for a conduit
|
306
|
+
# shards is an array of shard objects with id and transport properties
|
307
|
+
shards = [
|
308
|
+
{
|
309
|
+
id: "0",
|
310
|
+
transport: {
|
311
|
+
method: "webhook",
|
312
|
+
callback: "https://example.com/webhooks/callback",
|
313
|
+
secret: "your-secret"
|
314
|
+
}
|
315
|
+
}
|
316
|
+
]
|
317
|
+
@client.eventsub_conduits.update_shards(id: "abc123-def456", shards: shards)
|
318
|
+
```
|
319
|
+
|
278
320
|
### Banned Events
|
279
321
|
|
280
322
|
```ruby
|
@@ -564,6 +606,180 @@ messages = [{msg_id: "abc1", msg_text: "is this allowed?"}, {msg_id: "abc2", msg
|
|
564
606
|
@client.warnings.create broadcaster_id: 123, moderator_id: 123, user_id: 321, reason: "dont do that"
|
565
607
|
```
|
566
608
|
|
609
|
+
### Streams
|
610
|
+
|
611
|
+
```ruby
|
612
|
+
# List live streams
|
613
|
+
# Available parameters: user_id, user_login, game_id, type, language, first, before, after
|
614
|
+
@client.streams.list
|
615
|
+
@client.streams.list(game_id: "509658")
|
616
|
+
@client.streams.list(user_login: "twitchdev")
|
617
|
+
|
618
|
+
# Get followed streams for a user
|
619
|
+
# Required scope: user:read:follows
|
620
|
+
# user_id must match the currently authenticated user
|
621
|
+
@client.streams.followed(user_id: 123)
|
622
|
+
```
|
623
|
+
|
624
|
+
### Polls
|
625
|
+
|
626
|
+
```ruby
|
627
|
+
# List polls for a broadcaster
|
628
|
+
# broadcaster_id must match the currently authenticated user
|
629
|
+
@client.polls.list(broadcaster_id: 123)
|
630
|
+
|
631
|
+
# Create a poll
|
632
|
+
# broadcaster_id must match the currently authenticated user
|
633
|
+
# duration is in seconds (15-1800)
|
634
|
+
choices = [
|
635
|
+
{ title: "Choice 1" },
|
636
|
+
{ title: "Choice 2" }
|
637
|
+
]
|
638
|
+
@client.polls.create(broadcaster_id: 123, title: "What should I play?", choices: choices, duration: 300)
|
639
|
+
|
640
|
+
# End a poll
|
641
|
+
# broadcaster_id must match the currently authenticated user
|
642
|
+
# status can be "TERMINATED" or "ARCHIVED"
|
643
|
+
@client.polls.end(broadcaster_id: 123, id: "poll-id", status: "terminated")
|
644
|
+
```
|
645
|
+
|
646
|
+
### Predictions
|
647
|
+
|
648
|
+
```ruby
|
649
|
+
# List predictions for a broadcaster
|
650
|
+
# broadcaster_id must match the currently authenticated user
|
651
|
+
@client.predictions.list(broadcaster_id: 123)
|
652
|
+
|
653
|
+
# Create a prediction
|
654
|
+
# broadcaster_id must match the currently authenticated user
|
655
|
+
# duration is in seconds (30-1800)
|
656
|
+
outcomes = [
|
657
|
+
{ title: "Outcome 1" },
|
658
|
+
{ title: "Outcome 2" }
|
659
|
+
]
|
660
|
+
@client.predictions.create(broadcaster_id: 123, title: "Will I win?", outcomes: outcomes, duration: 600)
|
661
|
+
|
662
|
+
# End a prediction
|
663
|
+
# broadcaster_id must match the currently authenticated user
|
664
|
+
# status can be "RESOLVED", "CANCELED", or "LOCKED"
|
665
|
+
# winning_outcome_id is required when status is "RESOLVED"
|
666
|
+
@client.predictions.end(broadcaster_id: 123, id: "prediction-id", status: "resolved", winning_outcome_id: "outcome-id")
|
667
|
+
```
|
668
|
+
|
669
|
+
### Subscriptions
|
670
|
+
|
671
|
+
```ruby
|
672
|
+
# Get all subscriptions for a broadcaster
|
673
|
+
# Required scope: channel:read:subscriptions
|
674
|
+
# broadcaster_id must match the currently authenticated user
|
675
|
+
@client.subscriptions.list(broadcaster_id: 123)
|
676
|
+
|
677
|
+
# Check if a user is subscribed to a broadcaster
|
678
|
+
# Required scope: user:read:subscriptions
|
679
|
+
# user_id must match the currently authenticated user
|
680
|
+
@client.subscriptions.is_subscribed(broadcaster_id: 123, user_id: 456)
|
681
|
+
|
682
|
+
# Get subscription counts and points for a broadcaster
|
683
|
+
# Required scope: channel:read:subscriptions
|
684
|
+
# broadcaster_id must match the currently authenticated user
|
685
|
+
@client.subscriptions.counts(broadcaster_id: 123)
|
686
|
+
```
|
687
|
+
|
688
|
+
### Search
|
689
|
+
|
690
|
+
```ruby
|
691
|
+
# Search for categories/games
|
692
|
+
@client.search.categories(query: "Just Chatting")
|
693
|
+
|
694
|
+
# Search for channels
|
695
|
+
@client.search.channels(query: "twitchdev")
|
696
|
+
```
|
697
|
+
|
698
|
+
### Stream Schedule
|
699
|
+
|
700
|
+
```ruby
|
701
|
+
# Get stream schedule for a broadcaster
|
702
|
+
# broadcaster_id must match the currently authenticated user
|
703
|
+
@client.stream_schedule.list(broadcaster_id: 123)
|
704
|
+
|
705
|
+
# Get iCalendar format of stream schedule
|
706
|
+
# broadcaster_id must match the currently authenticated user
|
707
|
+
@client.stream_schedule.icalendar(broadcaster_id: 123)
|
708
|
+
|
709
|
+
# Update stream schedule settings
|
710
|
+
# broadcaster_id must match the currently authenticated user
|
711
|
+
@client.stream_schedule.update(broadcaster_id: 123, is_vacation_enabled: true)
|
712
|
+
|
713
|
+
# Create a schedule segment
|
714
|
+
# broadcaster_id must match the currently authenticated user
|
715
|
+
@client.stream_schedule.create_segment(
|
716
|
+
broadcaster_id: 123,
|
717
|
+
start_time: "2023-08-01T16:00:00Z",
|
718
|
+
timezone: "America/New_York",
|
719
|
+
duration: "240",
|
720
|
+
is_recurring: false,
|
721
|
+
category_id: "509658",
|
722
|
+
title: "Special Stream"
|
723
|
+
)
|
724
|
+
|
725
|
+
# Update a schedule segment
|
726
|
+
# broadcaster_id must match the currently authenticated user
|
727
|
+
@client.stream_schedule.update_segment(broadcaster_id: 123, id: "segment-id", title: "Updated Title")
|
728
|
+
|
729
|
+
# Delete a schedule segment
|
730
|
+
# broadcaster_id must match the currently authenticated user
|
731
|
+
@client.stream_schedule.delete_segment(broadcaster_id: 123, id: "segment-id")
|
732
|
+
```
|
733
|
+
|
734
|
+
### Stream Markers
|
735
|
+
|
736
|
+
```ruby
|
737
|
+
# Create a stream marker
|
738
|
+
# Required scope: channel:manage:broadcast
|
739
|
+
# user_id must match the currently authenticated user
|
740
|
+
@client.stream_markers.create(user_id: 123, description: "Important moment")
|
741
|
+
|
742
|
+
# Get stream markers for a user or video
|
743
|
+
# Required scope: user:read:broadcast
|
744
|
+
# user_id must match the currently authenticated user
|
745
|
+
@client.stream_markers.list(user_id: 123)
|
746
|
+
@client.stream_markers.list(video_id: "video-id")
|
747
|
+
```
|
748
|
+
|
749
|
+
### Tags
|
750
|
+
|
751
|
+
```ruby
|
752
|
+
# Get all stream tags
|
753
|
+
@client.tags.list
|
754
|
+
|
755
|
+
# Get stream tags for a specific broadcaster
|
756
|
+
@client.tags.stream(broadcaster_id: 123)
|
757
|
+
|
758
|
+
# Replace stream tags for a broadcaster
|
759
|
+
# Required scope: channel:manage:broadcast
|
760
|
+
# broadcaster_id must match the currently authenticated user
|
761
|
+
tag_ids = ["tag-id-1", "tag-id-2"]
|
762
|
+
@client.tags.replace(broadcaster_id: 123, tag_ids: tag_ids)
|
763
|
+
```
|
764
|
+
|
765
|
+
### Hype Train Events
|
766
|
+
|
767
|
+
```ruby
|
768
|
+
# Get hype train events for a broadcaster
|
769
|
+
# Required scope: channel:read:hype_train
|
770
|
+
# broadcaster_id must match the currently authenticated user
|
771
|
+
@client.hype_train_events.list(broadcaster_id: 123)
|
772
|
+
```
|
773
|
+
|
774
|
+
### Moderator Events
|
775
|
+
|
776
|
+
```ruby
|
777
|
+
# Get moderator events for a broadcaster
|
778
|
+
# Required scope: moderation:read
|
779
|
+
# broadcaster_id must match the currently authenticated user
|
780
|
+
@client.moderator_events.list(broadcaster_id: 123)
|
781
|
+
```
|
782
|
+
|
567
783
|
|
568
784
|
## Contributing
|
569
785
|
|
@@ -0,0 +1,128 @@
|
|
1
|
+
module Twitch
|
2
|
+
class ErrorGenerator < StandardError
|
3
|
+
attr_reader :http_status_code
|
4
|
+
attr_reader :twitch_error_code
|
5
|
+
attr_reader :twitch_error_message
|
6
|
+
|
7
|
+
def initialize(response_body, http_status_code)
|
8
|
+
@response_body = response_body
|
9
|
+
@http_status_code = http_status_code
|
10
|
+
set_twitch_error_values
|
11
|
+
super(build_message)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def set_twitch_error_values
|
17
|
+
@twitch_error_code = @response_body.dig("error")
|
18
|
+
@twitch_error_message = @response_body.dig("message")
|
19
|
+
end
|
20
|
+
|
21
|
+
def error_message
|
22
|
+
@twitch_error_message || @response_body.dig("error")
|
23
|
+
rescue NoMethodError
|
24
|
+
"An unknown error occurred."
|
25
|
+
end
|
26
|
+
|
27
|
+
def build_message
|
28
|
+
if twitch_error_code.nil?
|
29
|
+
return "Error #{@http_status_code}: #{error_message}"
|
30
|
+
end
|
31
|
+
"Error #{@http_status_code}: #{error_message} '#{twitch_error_message}'"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
module Errors
|
36
|
+
class BadRequestError < ErrorGenerator
|
37
|
+
private
|
38
|
+
|
39
|
+
def error_message
|
40
|
+
"Your request was malformed."
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class AuthenticationMissingError < ErrorGenerator
|
45
|
+
private
|
46
|
+
|
47
|
+
def error_message
|
48
|
+
"You did not supply valid authentication credentials."
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class ForbiddenError < ErrorGenerator
|
53
|
+
private
|
54
|
+
|
55
|
+
def error_message
|
56
|
+
"You are not allowed to perform that action."
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
class EntityNotFoundError < ErrorGenerator
|
61
|
+
private
|
62
|
+
|
63
|
+
def error_message
|
64
|
+
"No results were found for your request."
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
class ConflictError < ErrorGenerator
|
69
|
+
private
|
70
|
+
|
71
|
+
def error_message
|
72
|
+
"Your request was a conflict."
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
class TooManyRequestsError < ErrorGenerator
|
77
|
+
private
|
78
|
+
|
79
|
+
def error_message
|
80
|
+
"Your request exceeded the API rate limit."
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
class InternalError < ErrorGenerator
|
85
|
+
private
|
86
|
+
|
87
|
+
def error_message
|
88
|
+
"We were unable to perform the request due to server-side problems."
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class ServiceUnavailableError < ErrorGenerator
|
93
|
+
private
|
94
|
+
|
95
|
+
def error_message
|
96
|
+
"You have been rate limited for sending more than 20 requests per second."
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
class NotImplementedError < ErrorGenerator
|
101
|
+
private
|
102
|
+
|
103
|
+
def error_message
|
104
|
+
"This resource has not been implemented."
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
class ErrorFactory
|
110
|
+
HTTP_ERROR_MAP = {
|
111
|
+
400 => Errors::BadRequestError,
|
112
|
+
401 => Errors::AuthenticationMissingError,
|
113
|
+
403 => Errors::ForbiddenError,
|
114
|
+
404 => Errors::EntityNotFoundError,
|
115
|
+
409 => Errors::ConflictError,
|
116
|
+
429 => Errors::TooManyRequestsError,
|
117
|
+
500 => Errors::InternalError,
|
118
|
+
503 => Errors::ServiceUnavailableError,
|
119
|
+
501 => Errors::NotImplementedError
|
120
|
+
}.freeze
|
121
|
+
|
122
|
+
def self.create(response_body, http_status_code)
|
123
|
+
status = http_status_code
|
124
|
+
error_class = HTTP_ERROR_MAP[status] || ErrorGenerator
|
125
|
+
error_class.new(response_body, http_status_code) if error_class
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
data/lib/twitch/resource.rb
CHANGED
@@ -29,31 +29,20 @@ module Twitch
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def handle_response(response)
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
raise Error, "Error 429: Your request exceeded the API rate limit. '#{response.body["error"]}'"
|
47
|
-
when 500
|
48
|
-
raise Error, "Error 500: We were unable to perform the request due to server-side problems. '#{response.body["error"]}'"
|
49
|
-
when 503
|
50
|
-
raise Error, "Error 503: You have been rate limited for sending more than 20 requests per second. '#{response.body["error"]}'"
|
51
|
-
when 204
|
52
|
-
# 204 is a response for success on Twitch's API
|
53
|
-
return true
|
54
|
-
end
|
55
|
-
|
56
|
-
response
|
32
|
+
return true if response.status == 204
|
33
|
+
return response unless error?(response)
|
34
|
+
|
35
|
+
raise_error(response)
|
36
|
+
end
|
37
|
+
|
38
|
+
def error?(response)
|
39
|
+
[ 400, 401, 403, 404, 409, 429, 500, 501, 503 ].include?(response.status) ||
|
40
|
+
response.body&.key?("error")
|
41
|
+
end
|
42
|
+
|
43
|
+
def raise_error(response)
|
44
|
+
error = Twitch::ErrorFactory.create(response.body, response.status)
|
45
|
+
raise error if error
|
57
46
|
end
|
58
47
|
end
|
59
48
|
end
|
data/lib/twitch/version.rb
CHANGED
data/lib/twitch.rb
CHANGED
@@ -1,11 +1,16 @@
|
|
1
1
|
require "faraday"
|
2
2
|
require "json"
|
3
|
+
require "ostruct"
|
3
4
|
require "twitch/version"
|
4
5
|
|
5
6
|
module Twitch
|
7
|
+
autoload :Error, "twitch/error"
|
8
|
+
autoload :Errors, "twitch/error_generator"
|
9
|
+
autoload :ErrorGenerator, "twitch/error_generator"
|
10
|
+
autoload :ErrorFactory, "twitch/error_generator"
|
11
|
+
|
6
12
|
autoload :Client, "twitch/client"
|
7
13
|
autoload :Collection, "twitch/collection"
|
8
|
-
autoload :Error, "twitch/error"
|
9
14
|
autoload :Resource, "twitch/resource"
|
10
15
|
autoload :Object, "twitch/object"
|
11
16
|
|
data/mise.toml
ADDED
data/twitchrb.gemspec
CHANGED
@@ -24,5 +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.
|
27
|
+
spec.add_dependency "faraday", "~> 2.11"
|
28
|
+
spec.add_dependency "ostruct", "~> 0.6.0"
|
28
29
|
end
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: twitchrb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dean Perry
|
8
|
-
autorequire:
|
9
8
|
bindir: exe
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: faraday
|
@@ -16,15 +15,28 @@ dependencies:
|
|
16
15
|
requirements:
|
17
16
|
- - "~>"
|
18
17
|
- !ruby/object:Gem::Version
|
19
|
-
version: '2.
|
18
|
+
version: '2.11'
|
20
19
|
type: :runtime
|
21
20
|
prerelease: false
|
22
21
|
version_requirements: !ruby/object:Gem::Requirement
|
23
22
|
requirements:
|
24
23
|
- - "~>"
|
25
24
|
- !ruby/object:Gem::Version
|
26
|
-
version: '2.
|
27
|
-
|
25
|
+
version: '2.11'
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: ostruct
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - "~>"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.6.0
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: 0.6.0
|
28
40
|
email:
|
29
41
|
- dean@deanpcmad.com
|
30
42
|
executables: []
|
@@ -33,6 +45,7 @@ extra_rdoc_files: []
|
|
33
45
|
files:
|
34
46
|
- ".env.example"
|
35
47
|
- ".github/FUNDING.yml"
|
48
|
+
- ".github/dependabot.yml"
|
36
49
|
- ".github/workflows/ci.yml"
|
37
50
|
- ".gitignore"
|
38
51
|
- ".rubocop.yml"
|
@@ -47,6 +60,7 @@ files:
|
|
47
60
|
- lib/twitch/client.rb
|
48
61
|
- lib/twitch/collection.rb
|
49
62
|
- lib/twitch/error.rb
|
63
|
+
- lib/twitch/error_generator.rb
|
50
64
|
- lib/twitch/oauth.rb
|
51
65
|
- lib/twitch/object.rb
|
52
66
|
- lib/twitch/objects/automod_setting.rb
|
@@ -106,7 +120,6 @@ files:
|
|
106
120
|
- lib/twitch/resources/custom_reward_redemptions.rb
|
107
121
|
- lib/twitch/resources/custom_rewards.rb
|
108
122
|
- lib/twitch/resources/emotes.rb
|
109
|
-
- lib/twitch/resources/event_sub_conduit.rb
|
110
123
|
- lib/twitch/resources/eventsub_conduits.rb
|
111
124
|
- lib/twitch/resources/eventsub_subscriptions.rb
|
112
125
|
- lib/twitch/resources/games.rb
|
@@ -132,6 +145,7 @@ files:
|
|
132
145
|
- lib/twitch/resources/whispers.rb
|
133
146
|
- lib/twitch/version.rb
|
134
147
|
- lib/twitchrb.rb
|
148
|
+
- mise.toml
|
135
149
|
- twitchrb.gemspec
|
136
150
|
homepage: https://deanpcmad.com
|
137
151
|
licenses:
|
@@ -139,7 +153,6 @@ licenses:
|
|
139
153
|
metadata:
|
140
154
|
homepage_uri: https://deanpcmad.com
|
141
155
|
source_code_uri: https://github.com/deanpcmad/twitchrb
|
142
|
-
post_install_message:
|
143
156
|
rdoc_options: []
|
144
157
|
require_paths:
|
145
158
|
- lib
|
@@ -154,8 +167,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
154
167
|
- !ruby/object:Gem::Version
|
155
168
|
version: '0'
|
156
169
|
requirements: []
|
157
|
-
rubygems_version: 3.
|
158
|
-
signing_key:
|
170
|
+
rubygems_version: 3.6.7
|
159
171
|
specification_version: 4
|
160
172
|
summary: A Ruby library for interacting with the Twitch Helix API
|
161
173
|
test_files: []
|
@@ -1,19 +0,0 @@
|
|
1
|
-
module Twitch
|
2
|
-
class EventSubSubscriptionsResource < Resource
|
3
|
-
def list(**params)
|
4
|
-
response = get_request("eventsub/subscriptions", params: params)
|
5
|
-
Collection.from_response(response, type: EventSubSubscription)
|
6
|
-
end
|
7
|
-
|
8
|
-
def create(type:, version:, condition:, transport:, **params)
|
9
|
-
attributes = { type: type, version: version, condition: condition, transport: transport }.merge(params)
|
10
|
-
response = post_request("eventsub/subscriptions", body: attributes)
|
11
|
-
|
12
|
-
EventSubSubscription.new(response.body.dig("data")[0]) if response.success?
|
13
|
-
end
|
14
|
-
|
15
|
-
def delete(id:)
|
16
|
-
delete_request("eventsub/subscriptions", params: { id: id })
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|