twitchrb 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.env.example +3 -0
- data/.github/FUNDING.yml +4 -0
- data/.gitignore +1 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +28 -9
- data/README.md +46 -6
- data/bin/console +5 -0
- data/lib/twitch/client.rb +131 -75
- data/lib/twitch/collection.rb +21 -0
- data/lib/twitch/error.rb +4 -0
- data/lib/twitch/object.rb +19 -0
- data/lib/twitch/objects/badge.rb +4 -0
- data/lib/twitch/objects/banned_event.rb +4 -0
- data/lib/twitch/objects/banned_user.rb +4 -0
- data/lib/twitch/objects/blocked_user.rb +4 -0
- data/lib/twitch/objects/channel.rb +4 -0
- data/lib/twitch/objects/channel_editor.rb +4 -0
- data/lib/twitch/objects/clip.rb +4 -0
- data/lib/twitch/objects/custom_reward.rb +4 -0
- data/lib/twitch/objects/custom_reward_redemption.rb +4 -0
- data/lib/twitch/objects/emote.rb +4 -0
- data/lib/twitch/objects/event_sub_subscription.rb +4 -0
- data/lib/twitch/objects/followed_user.rb +4 -0
- data/lib/twitch/objects/game.rb +4 -0
- data/lib/twitch/objects/goal.rb +4 -0
- data/lib/twitch/objects/hype_train_event.rb +4 -0
- data/lib/twitch/objects/moderator.rb +4 -0
- data/lib/twitch/objects/moderator_event.rb +4 -0
- data/lib/twitch/objects/poll.rb +4 -0
- data/lib/twitch/objects/prediction.rb +4 -0
- data/lib/twitch/objects/search_result.rb +4 -0
- data/lib/twitch/objects/stream.rb +4 -0
- data/lib/twitch/objects/stream_marker.rb +4 -0
- data/lib/twitch/objects/stream_schedule.rb +4 -0
- data/lib/twitch/objects/subscription.rb +4 -0
- data/lib/twitch/objects/subscription_count.rb +4 -0
- data/lib/twitch/objects/tag.rb +4 -0
- data/lib/twitch/objects/user.rb +4 -0
- data/lib/twitch/objects/video.rb +4 -0
- data/lib/twitch/resource.rb +57 -0
- data/lib/twitch/resources/badges.rb +15 -0
- data/lib/twitch/resources/banned_events.rb +10 -0
- data/lib/twitch/resources/banned_users.rb +11 -0
- data/lib/twitch/resources/channels.rb +20 -0
- data/lib/twitch/resources/clips.rb +19 -0
- data/lib/twitch/resources/custom_reward_redemptions.rb +22 -0
- data/lib/twitch/resources/custom_rewards.rb +30 -0
- data/lib/twitch/resources/emotes.rb +20 -0
- data/lib/twitch/resources/event_sub_subscriptions.rb +21 -0
- data/lib/twitch/resources/games.rb +20 -0
- data/lib/twitch/resources/goals.rb +12 -0
- data/lib/twitch/resources/hype_train_events.rb +12 -0
- data/lib/twitch/resources/moderator_events.rb +11 -0
- data/lib/twitch/resources/moderators.rb +11 -0
- data/lib/twitch/resources/polls.rb +27 -0
- data/lib/twitch/resources/predictions.rb +32 -0
- data/lib/twitch/resources/search.rb +17 -0
- data/lib/twitch/resources/stream_markers.rb +19 -0
- data/lib/twitch/resources/stream_schedule.rb +47 -0
- data/lib/twitch/resources/streams.rb +19 -0
- data/lib/twitch/resources/subscriptions.rb +73 -0
- data/lib/twitch/resources/tags.rb +20 -0
- data/lib/twitch/resources/users.rb +54 -0
- data/lib/twitch/resources/videos.rb +17 -0
- data/lib/twitch/version.rb +1 -1
- data/lib/twitch.rb +80 -32
- data/twitchrb.gemspec +3 -2
- metadata +79 -16
- data/lib/twitch/badges.rb +0 -39
- data/lib/twitch/channels.rb +0 -25
- data/lib/twitch/emotes.rb +0 -58
- data/lib/twitch/games.rb +0 -49
- data/lib/twitch/initializable.rb +0 -16
- data/lib/twitch/kraken/channels.rb +0 -22
- data/lib/twitch/kraken/clips.rb +0 -22
- data/lib/twitch/kraken/user.rb +0 -23
- data/lib/twitch/kraken/users.rb +0 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9eee2d6f7cc0434ccb49cb42e12020ac4581f3c7d51c2e58696b0a0fe22db68b
|
4
|
+
data.tar.gz: 0060beeceb9c3ca2062ac56457d00f18cb3a406cd4c6d7149406b3a53861e962
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 85c8d5fa26d7c37e13061bb45e071fc7eb02fdf68ba9bcb5e76e2c3964f6451916aa95f2b8584f9171954a34b4dc8a35303ff9629c19fa1a6c1a043d41a87913
|
7
|
+
data.tar.gz: 739d84bacdff4c31a2f63b7ccae655e1cc8661ca3346ab620db70792082777ab05da834c8d09874494654bb816f393b52b4cd445db424d693b6c07159e43712c
|
data/.env.example
ADDED
data/.github/FUNDING.yml
ADDED
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,26 +1,45 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
twitchrb (0.
|
5
|
-
|
4
|
+
twitchrb (0.2.0)
|
5
|
+
faraday (~> 1.7)
|
6
|
+
faraday_middleware (~> 1.1)
|
6
7
|
|
7
8
|
GEM
|
8
9
|
remote: https://rubygems.org/
|
9
10
|
specs:
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
11
|
+
dotenv (2.7.6)
|
12
|
+
faraday (1.8.0)
|
13
|
+
faraday-em_http (~> 1.0)
|
14
|
+
faraday-em_synchrony (~> 1.0)
|
15
|
+
faraday-excon (~> 1.1)
|
16
|
+
faraday-httpclient (~> 1.0.1)
|
17
|
+
faraday-net_http (~> 1.0)
|
18
|
+
faraday-net_http_persistent (~> 1.1)
|
19
|
+
faraday-patron (~> 1.0)
|
20
|
+
faraday-rack (~> 1.0)
|
21
|
+
multipart-post (>= 1.2, < 3)
|
22
|
+
ruby2_keywords (>= 0.0.4)
|
23
|
+
faraday-em_http (1.0.0)
|
24
|
+
faraday-em_synchrony (1.0.0)
|
25
|
+
faraday-excon (1.1.0)
|
26
|
+
faraday-httpclient (1.0.1)
|
27
|
+
faraday-net_http (1.0.1)
|
28
|
+
faraday-net_http_persistent (1.2.0)
|
29
|
+
faraday-patron (1.0.0)
|
30
|
+
faraday-rack (1.0.0)
|
31
|
+
faraday_middleware (1.1.0)
|
32
|
+
faraday (~> 1.0)
|
16
33
|
minitest (5.14.1)
|
17
|
-
|
34
|
+
multipart-post (2.1.1)
|
18
35
|
rake (12.3.3)
|
36
|
+
ruby2_keywords (0.0.5)
|
19
37
|
|
20
38
|
PLATFORMS
|
21
39
|
ruby
|
22
40
|
|
23
41
|
DEPENDENCIES
|
42
|
+
dotenv
|
24
43
|
minitest (~> 5.0)
|
25
44
|
rake (~> 12.0)
|
26
45
|
twitchrb!
|
data/README.md
CHANGED
@@ -2,9 +2,9 @@
|
|
2
2
|
|
3
3
|
**This library is a work in progress**
|
4
4
|
|
5
|
-
|
5
|
+
TwitchRB is a Ruby library for intereacting with the Twitch API.
|
6
6
|
|
7
|
-
It
|
7
|
+
It only supports the Helix API as v5 is deprecated.
|
8
8
|
|
9
9
|
## Installation
|
10
10
|
|
@@ -14,15 +14,55 @@ Add this line to your application's Gemfile:
|
|
14
14
|
gem "twitchrb", require: "twitch"
|
15
15
|
```
|
16
16
|
|
17
|
-
|
17
|
+
## Usage
|
18
18
|
|
19
|
-
|
19
|
+
### Set Client Details
|
20
20
|
|
21
|
+
Firstly you'll need to set a Client ID, Secret Key and an Access Token.
|
21
22
|
|
22
|
-
|
23
|
+
An access token is required because the Helix API requires authentication.
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
@client = Twitch::Client.new(client_id: "", secret_key: "", access_token: "")
|
27
|
+
```
|
28
|
+
|
29
|
+
### Users
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
@client.users.get_by_id(user_id: 141981764)
|
33
|
+
@client.users.get_by_username(username: "twitchdev")
|
34
|
+
```
|
35
|
+
|
36
|
+
### Channels
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
@client.channels.get(broadcaster_id: 141981764)
|
40
|
+
```
|
41
|
+
|
42
|
+
### Videos
|
23
43
|
|
24
|
-
|
44
|
+
```ruby
|
45
|
+
@client.videos.get(user_id: 141981764)
|
46
|
+
```
|
47
|
+
|
48
|
+
### Emotes
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
@client.emotes.global
|
52
|
+
@client.emotes.channel(broadcaster_id: 141981764)
|
53
|
+
@client.emotes.sets(emote_set_id: 301590448)
|
54
|
+
```
|
55
|
+
|
56
|
+
### Badges
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
@client.badges.global
|
60
|
+
@client.badges.channel(broadcaster_id: 141981764)
|
61
|
+
```
|
62
|
+
|
63
|
+
## Contributing
|
25
64
|
|
65
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/twitchrb/twitchrb.
|
26
66
|
|
27
67
|
## License
|
28
68
|
|
data/bin/console
CHANGED
@@ -3,6 +3,9 @@
|
|
3
3
|
require "bundler/setup"
|
4
4
|
require "twitch"
|
5
5
|
|
6
|
+
# Load environment variables from .env file
|
7
|
+
require 'dotenv/load'
|
8
|
+
|
6
9
|
# You can add fixtures and/or initialization code here to make experimenting
|
7
10
|
# with your gem easier. You can also use a different console, if you like.
|
8
11
|
|
@@ -10,5 +13,7 @@ require "twitch"
|
|
10
13
|
# require "pry"
|
11
14
|
# Pry.start
|
12
15
|
|
16
|
+
@client = Twitch::Client.new(client_id: ENV["TWITCH_CLIENT_ID"], client_secret: ENV["TWITCH_CLIENT_SECRET"], access_token: ENV["TWITCH_ACCESS_TOKEN"])
|
17
|
+
|
13
18
|
require "irb"
|
14
19
|
IRB.start(__FILE__)
|
data/lib/twitch/client.rb
CHANGED
@@ -1,92 +1,148 @@
|
|
1
|
-
require "httparty"
|
1
|
+
# require "httparty"
|
2
|
+
|
3
|
+
|
4
|
+
# def headers(kind)
|
5
|
+
# if kind == :helix
|
6
|
+
# {
|
7
|
+
# "Client-ID" => @client_id,
|
8
|
+
# "Accept" => "application/json",
|
9
|
+
# "Content-Type" => "application/json",
|
10
|
+
# "Authorization" => "Bearer #{@access_token}"
|
11
|
+
# }
|
12
|
+
# else
|
13
|
+
# {
|
14
|
+
# "Client-ID" => @client_id,
|
15
|
+
# "Accept" => "application/vnd.twitchtv.v5+json",
|
16
|
+
# # "Authorization" => "OAuth #{@access_token}"
|
17
|
+
# }
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
|
21
|
+
|
2
22
|
|
3
23
|
module Twitch
|
4
24
|
class Client
|
25
|
+
BASE_URL = "https://api.twitch.tv/helix"
|
5
26
|
|
6
|
-
|
7
|
-
def initialize(client_id, access_token=nil)
|
8
|
-
puts "initialize"
|
27
|
+
attr_reader :client_id, :client_secret, :access_token, :adapter
|
9
28
|
|
29
|
+
def initialize(client_id:, client_secret:, access_token:, adapter: Faraday.default_adapter, stubs: nil)
|
10
30
|
@client_id = client_id
|
31
|
+
@client_secret = client_secret
|
11
32
|
@access_token = access_token
|
33
|
+
@adapter = adapter
|
12
34
|
|
13
|
-
#
|
14
|
-
|
15
|
-
# @client_secret = client_secret
|
16
|
-
# @access_token = access_token
|
17
|
-
# else
|
18
|
-
# raise Twitch::ClientError.new('Client ID or Client Secret not set')
|
19
|
-
# end
|
20
|
-
end
|
21
|
-
|
22
|
-
def headers(kind)
|
23
|
-
if kind == :helix
|
24
|
-
{
|
25
|
-
"Client-ID" => @client_id,
|
26
|
-
"Accept" => "application/json",
|
27
|
-
"Authorization" => "Bearer #{@access_token}"
|
28
|
-
}
|
29
|
-
else
|
30
|
-
{
|
31
|
-
"Client-ID" => @client_id,
|
32
|
-
"Accept" => "application/vnd.twitchtv.v5+json",
|
33
|
-
# "Authorization" => "OAuth #{@access_token}"
|
34
|
-
}
|
35
|
-
end
|
35
|
+
# Test stubs for requests
|
36
|
+
@stubs = stubs
|
36
37
|
end
|
37
38
|
|
39
|
+
def users
|
40
|
+
UsersResource.new(self)
|
41
|
+
end
|
38
42
|
|
39
|
-
def
|
40
|
-
|
41
|
-
headers: headers(kind)
|
42
|
-
})
|
43
|
-
|
44
|
-
# Force encoding as the reponse may have emojis
|
45
|
-
body = response.body.force_encoding('UTF-8')
|
46
|
-
|
47
|
-
success = case response.code
|
48
|
-
when 200
|
49
|
-
JSON.parse(body)
|
50
|
-
when 400
|
51
|
-
json = JSON.parse(body)
|
52
|
-
raise Twitch::Errors::NotFound, json['error']
|
53
|
-
when 503
|
54
|
-
raise Twitch::Errors::ServiceUnavailable
|
55
|
-
when 401, 403
|
56
|
-
puts body.inspect
|
57
|
-
raise Twitch::Errors::AccessDenied, "Access Denied for '#{@client_id}'"
|
58
|
-
when 400
|
59
|
-
json = JSON.parse(body)
|
60
|
-
raise Twitch::Errors::ValidationError, json['errors'].to_s
|
61
|
-
else
|
62
|
-
raise Twitch::Errors::CommunicationError, body
|
63
|
-
end
|
43
|
+
def channels
|
44
|
+
ChannelsResource.new(self)
|
64
45
|
end
|
65
46
|
|
66
|
-
def
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
47
|
+
def emotes
|
48
|
+
EmotesResource.new(self)
|
49
|
+
end
|
50
|
+
|
51
|
+
def badges
|
52
|
+
BadgesResource.new(self)
|
53
|
+
end
|
54
|
+
|
55
|
+
def games
|
56
|
+
GamesResource.new(self)
|
57
|
+
end
|
58
|
+
|
59
|
+
def videos
|
60
|
+
VideosResource.new(self)
|
61
|
+
end
|
62
|
+
|
63
|
+
def clips
|
64
|
+
ClipsResource.new(self)
|
65
|
+
end
|
66
|
+
|
67
|
+
def eventsub_subscriptions
|
68
|
+
EventSubSubscriptionsResource.new(self)
|
69
|
+
end
|
70
|
+
|
71
|
+
def banned_events
|
72
|
+
BannedEventsResource.new(self)
|
73
|
+
end
|
74
|
+
|
75
|
+
def banned_users
|
76
|
+
BannedUsersResource.new(self)
|
77
|
+
end
|
78
|
+
|
79
|
+
def moderators
|
80
|
+
ModeratorsResource.new(self)
|
81
|
+
end
|
82
|
+
|
83
|
+
def moderator_events
|
84
|
+
ModeratorEventsResource.new(self)
|
85
|
+
end
|
86
|
+
|
87
|
+
def polls
|
88
|
+
PollsResource.new(self)
|
89
89
|
end
|
90
90
|
|
91
|
+
def predictions
|
92
|
+
PredictionsResource.new(self)
|
93
|
+
end
|
94
|
+
|
95
|
+
def stream_schedule
|
96
|
+
StreamScheduleResource.new(self)
|
97
|
+
end
|
98
|
+
|
99
|
+
def search
|
100
|
+
SearchResource.new(self)
|
101
|
+
end
|
102
|
+
|
103
|
+
def streams
|
104
|
+
StreamsResource.new(self)
|
105
|
+
end
|
106
|
+
|
107
|
+
def stream_markers
|
108
|
+
StreamMarkersResource.new(self)
|
109
|
+
end
|
110
|
+
|
111
|
+
def subscriptions
|
112
|
+
SubscriptionsResource.new(self)
|
113
|
+
end
|
114
|
+
|
115
|
+
def tags
|
116
|
+
TagsResource.new(self)
|
117
|
+
end
|
118
|
+
|
119
|
+
def custom_rewards
|
120
|
+
CustomRewardsResource.new(self)
|
121
|
+
end
|
122
|
+
|
123
|
+
def custom_reward_redemptions
|
124
|
+
CustomRewardRedemptionsResource.new(self)
|
125
|
+
end
|
126
|
+
|
127
|
+
def goals
|
128
|
+
GoalsResource.new(self)
|
129
|
+
end
|
130
|
+
|
131
|
+
def hype_train_events
|
132
|
+
HypeTrainEventsResource.new(self)
|
133
|
+
end
|
134
|
+
|
135
|
+
def connection
|
136
|
+
@connection ||= Faraday.new(BASE_URL) do |conn|
|
137
|
+
conn.request :authorization, :Bearer, access_token
|
138
|
+
conn.headers = { "Client-ID": client_id }
|
139
|
+
conn.request :json
|
140
|
+
|
141
|
+
conn.response :dates
|
142
|
+
conn.response :json, content_type: "application/json"
|
143
|
+
|
144
|
+
conn.adapter adapter, @stubs
|
145
|
+
end
|
146
|
+
end
|
91
147
|
end
|
92
148
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Twitch
|
2
|
+
class Collection
|
3
|
+
attr_reader :data, :total, :cursor
|
4
|
+
|
5
|
+
def self.from_response(response, type:)
|
6
|
+
body = response.body
|
7
|
+
|
8
|
+
new(
|
9
|
+
data: body["data"].map { |attrs| type.new(attrs) },
|
10
|
+
total: body["data"].count,
|
11
|
+
cursor: body.dig("pagination", "cursor")
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(data:, total:, cursor:)
|
16
|
+
@data = data
|
17
|
+
@total = total
|
18
|
+
@cursor = cursor.nil? ? nil : cursor
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/twitch/error.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require "ostruct"
|
2
|
+
|
3
|
+
module Twitch
|
4
|
+
class Object < OpenStruct
|
5
|
+
def initialize(attributes)
|
6
|
+
super to_ostruct(attributes)
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_ostruct(obj)
|
10
|
+
if obj.is_a?(Hash)
|
11
|
+
OpenStruct.new(obj.map { |key, val| [key, to_ostruct(val)] }.to_h)
|
12
|
+
elsif obj.is_a?(Array)
|
13
|
+
obj.map { |o| to_ostruct(o) }
|
14
|
+
else # Assumed to be a primitive value
|
15
|
+
obj
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|