twitchrb 0.1.1 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/.env.example +3 -0
  3. data/.github/FUNDING.yml +4 -0
  4. data/.gitignore +1 -0
  5. data/Gemfile +1 -0
  6. data/Gemfile.lock +28 -9
  7. data/README.md +47 -7
  8. data/bin/console +5 -0
  9. data/lib/twitch/client.rb +110 -75
  10. data/lib/twitch/collection.rb +21 -0
  11. data/lib/twitch/error.rb +4 -0
  12. data/lib/twitch/object.rb +19 -0
  13. data/lib/twitch/objects/badge.rb +4 -0
  14. data/lib/twitch/objects/banned_event.rb +4 -0
  15. data/lib/twitch/objects/banned_user.rb +4 -0
  16. data/lib/twitch/objects/blocked_user.rb +4 -0
  17. data/lib/twitch/objects/channel.rb +4 -0
  18. data/lib/twitch/objects/channel_editor.rb +4 -0
  19. data/lib/twitch/objects/clip.rb +4 -0
  20. data/lib/twitch/objects/custom_reward.rb +4 -0
  21. data/lib/twitch/objects/custom_reward_redemption.rb +4 -0
  22. data/lib/twitch/objects/emote.rb +4 -0
  23. data/lib/twitch/objects/event_sub_subscription.rb +4 -0
  24. data/lib/twitch/objects/followed_user.rb +4 -0
  25. data/lib/twitch/objects/game.rb +4 -0
  26. data/lib/twitch/objects/goal.rb +4 -0
  27. data/lib/twitch/objects/hype_train_event.rb +4 -0
  28. data/lib/twitch/objects/moderator.rb +4 -0
  29. data/lib/twitch/objects/moderator_event.rb +4 -0
  30. data/lib/twitch/objects/poll.rb +4 -0
  31. data/lib/twitch/objects/prediction.rb +4 -0
  32. data/lib/twitch/objects/search_result.rb +4 -0
  33. data/lib/twitch/objects/stream.rb +4 -0
  34. data/lib/twitch/objects/stream_marker.rb +4 -0
  35. data/lib/twitch/objects/stream_schedule.rb +4 -0
  36. data/lib/twitch/objects/subscription.rb +4 -0
  37. data/lib/twitch/objects/subscription_count.rb +4 -0
  38. data/lib/twitch/objects/tag.rb +4 -0
  39. data/lib/twitch/objects/user.rb +4 -0
  40. data/lib/twitch/objects/video.rb +27 -0
  41. data/lib/twitch/resource.rb +57 -0
  42. data/lib/twitch/resources/badges.rb +15 -0
  43. data/lib/twitch/resources/banned_events.rb +10 -0
  44. data/lib/twitch/resources/banned_users.rb +11 -0
  45. data/lib/twitch/resources/channels.rb +20 -0
  46. data/lib/twitch/resources/clips.rb +23 -0
  47. data/lib/twitch/resources/custom_reward_redemptions.rb +22 -0
  48. data/lib/twitch/resources/custom_rewards.rb +30 -0
  49. data/lib/twitch/resources/emotes.rb +20 -0
  50. data/lib/twitch/resources/event_sub_subscriptions.rb +21 -0
  51. data/lib/twitch/resources/games.rb +20 -0
  52. data/lib/twitch/resources/goals.rb +12 -0
  53. data/lib/twitch/resources/hype_train_events.rb +12 -0
  54. data/lib/twitch/resources/moderator_events.rb +11 -0
  55. data/lib/twitch/resources/moderators.rb +11 -0
  56. data/lib/twitch/resources/polls.rb +27 -0
  57. data/lib/twitch/resources/predictions.rb +32 -0
  58. data/lib/twitch/resources/search.rb +17 -0
  59. data/lib/twitch/resources/stream_markers.rb +19 -0
  60. data/lib/twitch/resources/stream_schedule.rb +47 -0
  61. data/lib/twitch/resources/streams.rb +19 -0
  62. data/lib/twitch/resources/subscriptions.rb +32 -0
  63. data/lib/twitch/resources/tags.rb +20 -0
  64. data/lib/twitch/resources/users.rb +54 -0
  65. data/lib/twitch/resources/videos.rb +17 -0
  66. data/lib/twitch/version.rb +1 -1
  67. data/lib/twitch.rb +62 -34
  68. data/lib/twitchrb.rb +1 -0
  69. data/twitchrb.gemspec +3 -2
  70. metadata +80 -17
  71. data/.travis.yml +0 -6
  72. data/lib/twitch/badges.rb +0 -39
  73. data/lib/twitch/channels.rb +0 -25
  74. data/lib/twitch/emotes.rb +0 -58
  75. data/lib/twitch/games.rb +0 -49
  76. data/lib/twitch/initializable.rb +0 -16
  77. data/lib/twitch/kraken/channels.rb +0 -22
  78. data/lib/twitch/kraken/clips.rb +0 -22
  79. data/lib/twitch/kraken/user.rb +0 -23
  80. data/lib/twitch/kraken/users.rb +0 -33
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5f783023c0544d6ff69ae55aef0c2af9b1b179d438e435b1195dfe0895b686eb
4
- data.tar.gz: 2072fb3ec4460387493e2ad33745bcd0028770a9a1f91a0cbe2576c75b519822
3
+ metadata.gz: daefb5be94569e5fc14f586f740c4d469f4e76b60fc2b066870f2f55748b678f
4
+ data.tar.gz: e3ad55b7bc2fd6b9fa8d0453136b69b9ce25612cdd945114173a0b03a4026285
5
5
  SHA512:
6
- metadata.gz: 8dce1c0ff0bcd6dd7fa506f7bb0c090a883966e9d13a050593bed74b309dfb89dd9ddc6aff2f5ce80aa9c86fb1e5b01b739b7468ec1ea7ba9976212d59fa8b06
7
- data.tar.gz: e64c64c6a844131c553a71721dfd540dcb4cb0a40adf4b8f0f58a93543164587651f6d914540647fea5a2997ea8ae6198db16815ac7cb853ce2b33c4641f26a4
6
+ metadata.gz: 6d0c1fc6409e6878d840b75b502310a22891a7bb3e0ebf0de74362f9996cd6703624f0e4a280024b4659a1c6c8b0e45c6d7d70fab09d6d82ccdff6963d1a93ed
7
+ data.tar.gz: a1218538954e97ee5c06115dcc3925312f705e5b835074a0f536806eff4822f7b6e08c1739ddf9be18a01420b6511bbbb794f298b2fb734d207c8d58d929695c
data/.env.example ADDED
@@ -0,0 +1,3 @@
1
+ TWITCH_CLIENT_ID=
2
+ TWITCH_CLIENT_SECRET=
3
+ TWITCH_ACCESS_TOKEN=
@@ -0,0 +1,4 @@
1
+ # These are supported funding model platforms
2
+
3
+ github: deanpcmad
4
+ custom: https://www.buymeacoffee.com/deanpcmad
data/.gitignore CHANGED
@@ -6,3 +6,4 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+ .env
data/Gemfile CHANGED
@@ -5,3 +5,4 @@ gemspec
5
5
 
6
6
  gem "rake", "~> 12.0"
7
7
  gem "minitest", "~> 5.0"
8
+ gem "dotenv"
data/Gemfile.lock CHANGED
@@ -1,26 +1,45 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- twitchrb (0.1.1)
5
- httparty (~> 0.18.1)
4
+ twitchrb (0.2.3)
5
+ faraday (~> 1.7)
6
+ faraday_middleware (~> 1.1)
6
7
 
7
8
  GEM
8
9
  remote: https://rubygems.org/
9
10
  specs:
10
- httparty (0.18.1)
11
- mime-types (~> 3.0)
12
- multi_xml (>= 0.5.2)
13
- mime-types (3.3.1)
14
- mime-types-data (~> 3.2015)
15
- mime-types-data (3.2021.0225)
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.2.0)
32
+ faraday (~> 1.0)
16
33
  minitest (5.14.1)
17
- multi_xml (0.6.0)
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,27 +2,67 @@
2
2
 
3
3
  **This library is a work in progress**
4
4
 
5
- This RubyGem is a library for intereacting with the Twitch API.
5
+ TwitchRB is a Ruby library for intereacting with the Twitch API.
6
6
 
7
- It will allow you to easily interact with both the Kraken and Helix APIs.
7
+ It only supports the Helix API as v5 is deprecated.
8
8
 
9
9
  ## Installation
10
10
 
11
11
  Add this line to your application's Gemfile:
12
12
 
13
13
  ```ruby
14
- gem "twitchrb", require: "twitch"
14
+ gem "twitchrb"
15
15
  ```
16
16
 
17
- And then execute:
17
+ ## Usage
18
18
 
19
- $ bundle install
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
- ## Contributing
23
+ An access token is required because the Helix API requires authentication.
24
+
25
+ ```ruby
26
+ @client = Twitch::Client.new(client_id: "", client_secret: "", 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
- Bug reports and pull requests are welcome on GitHub at https://github.com/deanpcmad/twitchrb.
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,90 +1,125 @@
1
- require "httparty"
2
-
3
1
  module Twitch
4
2
  class Client
3
+ BASE_URL = "https://api.twitch.tv/helix"
5
4
 
6
- # def initialize(client_id, client_secret, access_token=nil)
7
- def initialize(client_id, access_token=nil)
8
- puts "initialize"
5
+ attr_reader :client_id, :client_secret, :access_token, :adapter
9
6
 
7
+ def initialize(client_id:, client_secret:, access_token:, adapter: Faraday.default_adapter, stubs: nil)
10
8
  @client_id = client_id
9
+ @client_secret = client_secret
11
10
  @access_token = access_token
11
+ @adapter = adapter
12
12
 
13
- # if client_id && client_secret
14
- # @client_id = client_id
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
13
+ # Test stubs for requests
14
+ @stubs = stubs
36
15
  end
37
16
 
17
+ def users
18
+ UsersResource.new(self)
19
+ end
38
20
 
39
- def get(kind, url)
40
- response = HTTParty.get("https://api.twitch.tv/#{kind}/#{url}", {
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
21
+ def channels
22
+ ChannelsResource.new(self)
23
+ end
24
+
25
+ def emotes
26
+ EmotesResource.new(self)
27
+ end
28
+
29
+ def badges
30
+ BadgesResource.new(self)
31
+ end
32
+
33
+ def games
34
+ GamesResource.new(self)
35
+ end
36
+
37
+ def videos
38
+ VideosResource.new(self)
39
+ end
40
+
41
+ def clips
42
+ ClipsResource.new(self)
43
+ end
44
+
45
+ def eventsub_subscriptions
46
+ EventSubSubscriptionsResource.new(self)
47
+ end
48
+
49
+ def banned_events
50
+ BannedEventsResource.new(self)
51
+ end
52
+
53
+ def banned_users
54
+ BannedUsersResource.new(self)
55
+ end
56
+
57
+ def moderators
58
+ ModeratorsResource.new(self)
59
+ end
60
+
61
+ def moderator_events
62
+ ModeratorEventsResource.new(self)
63
+ end
64
+
65
+ def polls
66
+ PollsResource.new(self)
64
67
  end
65
68
 
66
- def patch(kind, url, params={})
67
- response = HTTParty.patch("https://api.twitch.tv/#{kind}/#{url}", {
68
- headers: headers(kind),
69
- body: params
70
- })
71
-
72
- success = case response.code
73
- when 204
74
- return true
75
- when 400
76
- json = JSON.parse(response.body)
77
- raise Twitch::Errors::NotFound, json['error']
78
- when 503
79
- raise Twitch::Errors::ServiceUnavailable
80
- when 401, 403
81
- puts response.body.inspect
82
- raise Twitch::Errors::AccessDenied, "Access Denied for '#{@client_id}'"
83
- when 400
84
- json = JSON.parse(response.body)
85
- raise Twitch::Errors::ValidationError, json['errors'].to_s
86
- else
87
- raise Twitch::Errors::CommunicationError, response.body
69
+ def predictions
70
+ PredictionsResource.new(self)
71
+ end
72
+
73
+ def stream_schedule
74
+ StreamScheduleResource.new(self)
75
+ end
76
+
77
+ def search
78
+ SearchResource.new(self)
79
+ end
80
+
81
+ def streams
82
+ StreamsResource.new(self)
83
+ end
84
+
85
+ def stream_markers
86
+ StreamMarkersResource.new(self)
87
+ end
88
+
89
+ def subscriptions
90
+ SubscriptionsResource.new(self)
91
+ end
92
+
93
+ def tags
94
+ TagsResource.new(self)
95
+ end
96
+
97
+ def custom_rewards
98
+ CustomRewardsResource.new(self)
99
+ end
100
+
101
+ def custom_reward_redemptions
102
+ CustomRewardRedemptionsResource.new(self)
103
+ end
104
+
105
+ def goals
106
+ GoalsResource.new(self)
107
+ end
108
+
109
+ def hype_train_events
110
+ HypeTrainEventsResource.new(self)
111
+ end
112
+
113
+ def connection
114
+ @connection ||= Faraday.new(BASE_URL) do |conn|
115
+ conn.request :authorization, :Bearer, access_token
116
+ conn.headers = { "Client-ID": client_id }
117
+ conn.request :json
118
+
119
+ conn.response :dates
120
+ conn.response :json, content_type: "application/json"
121
+
122
+ conn.adapter adapter, @stubs
88
123
  end
89
124
  end
90
125
 
@@ -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
@@ -0,0 +1,4 @@
1
+ module Twitch
2
+ class Error < StandardError
3
+ end
4
+ end
@@ -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
@@ -0,0 +1,4 @@
1
+ module Twitch
2
+ class Badge < Object
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Twitch
2
+ class BannedEvent < Object
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Twitch
2
+ class BannedUser < Object
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Twitch
2
+ class BlockedUser < Object
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Twitch
2
+ class Channel < Object
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Twitch
2
+ class ChannelEditor < Object
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Twitch
2
+ class Clip < Object
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Twitch
2
+ class CustomReward < Object
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Twitch
2
+ class CustomRewardRedemption < Object
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Twitch
2
+ class Emote < Object
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Twitch
2
+ class EventSubSubscription < Object
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Twitch
2
+ class FollowedUser < Object
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Twitch
2
+ class Game < Object
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Twitch
2
+ class Goal < Object
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Twitch
2
+ class HypeTrainEvent < Object
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Twitch
2
+ class Moderator < Object
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Twitch
2
+ class ModeratorEvent < Object
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Twitch
2
+ class Poll < Object
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Twitch
2
+ class Prediction < Object
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Twitch
2
+ class SearchResult < Object
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Twitch
2
+ class Stream < Object
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Twitch
2
+ class StreamMarker < Object
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Twitch
2
+ class StreamSchedule < Object
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Twitch
2
+ class Subscription < Object
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Twitch
2
+ class SubscriptionCount < Object
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Twitch
2
+ class Tag < Object
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Twitch
2
+ class User < Object
3
+ end
4
+ end
@@ -0,0 +1,27 @@
1
+ module Twitch
2
+ class Video < Object
3
+
4
+ def initialize(options = {})
5
+ super options
6
+
7
+ self.thumbnail_url_large = generate_thumbnail_url_large
8
+ self.animated_url = generate_animated_url
9
+ end
10
+
11
+
12
+ # Generates the Large Thumbnail image URL
13
+ def generate_thumbnail_url_large
14
+ thumbnail_url.gsub("%{width}", "640").gsub("%{height}", "360")
15
+ end
16
+
17
+ # Generates a Storyboard/Animated image URL
18
+ def generate_animated_url
19
+ thumb = thumbnail_url.dup
20
+ thumb.gsub!("https://static-cdn.jtvnw.net/cf_vods/", "").gsub!("/thumb/thumb0-%{width}x%{height}.jpg", "storyboards/#{id}-strip-0.jpg")
21
+ split = thumb.split("/")
22
+
23
+ "https://#{split[0]}.cloudfront.net/#{split[1..].join("/")}"
24
+ end
25
+
26
+ end
27
+ end