twitchrb 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) 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 +46 -6
  8. data/bin/console +5 -0
  9. data/lib/twitch/client.rb +131 -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 +4 -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 +19 -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 +73 -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 +80 -32
  68. data/twitchrb.gemspec +3 -2
  69. metadata +79 -16
  70. data/lib/twitch/badges.rb +0 -39
  71. data/lib/twitch/channels.rb +0 -25
  72. data/lib/twitch/emotes.rb +0 -58
  73. data/lib/twitch/games.rb +0 -49
  74. data/lib/twitch/initializable.rb +0 -16
  75. data/lib/twitch/kraken/channels.rb +0 -22
  76. data/lib/twitch/kraken/clips.rb +0 -22
  77. data/lib/twitch/kraken/user.rb +0 -23
  78. data/lib/twitch/kraken/users.rb +0 -33
@@ -0,0 +1,57 @@
1
+ module Twitch
2
+ class Resource
3
+ attr_reader :client
4
+
5
+ def initialize(client)
6
+ @client = client
7
+ end
8
+
9
+ private
10
+
11
+ def get_request(url, params: {}, headers: {})
12
+ handle_response client.connection.get(url, params, headers)
13
+ end
14
+
15
+ def post_request(url, body:, headers: {})
16
+ handle_response client.connection.post(url, body, headers)
17
+ end
18
+
19
+ def patch_request(url, body:, headers: {})
20
+ handle_response client.connection.patch(url, body, headers)
21
+ end
22
+
23
+ def put_request(url, body:, headers: {})
24
+ handle_response client.connection.put(url, body, headers)
25
+ end
26
+
27
+ def delete_request(url, params: {}, headers: {})
28
+ handle_response client.connection.delete(url, params, headers)
29
+ end
30
+
31
+ def handle_response(response)
32
+ case response.status
33
+ when 400
34
+ raise Error, "Error 400: Your request was malformed. '#{response.body["message"]}'"
35
+ when 401
36
+ raise Error, "Error 401: You did not supply valid authentication credentials. '#{response.body["error"]}'"
37
+ when 403
38
+ raise Error, "Error 403: You are not allowed to perform that action. '#{response.body["error"]}'"
39
+ when 404
40
+ raise Error, "Error 404: No results were found for your request. '#{response.body["error"]}'"
41
+ when 409
42
+ raise Error, "Error 409: Your request was a conflict. '#{response.body["message"]}'"
43
+ when 429
44
+ raise Error, "Error 429: Your request exceeded the API rate limit. '#{response.body["error"]}'"
45
+ when 500
46
+ raise Error, "Error 500: We were unable to perform the request due to server-side problems. '#{response.body["error"]}'"
47
+ when 503
48
+ raise Error, "Error 503: You have been rate limited for sending more than 20 requests per second. '#{response.body["error"]}'"
49
+ when 204
50
+ # 204 is a response for success on Twitch's API
51
+ return true
52
+ end
53
+
54
+ response
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,15 @@
1
+ module Twitch
2
+ class BadgesResource < Resource
3
+
4
+ def channel(broadcaster_id:)
5
+ response = get_request("chat/badges?broadcaster_id=#{broadcaster_id}")
6
+ Collection.from_response(response, type: Badge)
7
+ end
8
+
9
+ def global
10
+ response = get_request("chat/badges/global")
11
+ Collection.from_response(response, type: Badge)
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,10 @@
1
+ module Twitch
2
+ class BannedEventsResource < Resource
3
+
4
+ def list(broadcaster_id:, **params)
5
+ response = get_request("moderation/banned/events", params: params.merge(broadcaster_id: broadcaster_id))
6
+ Collection.from_response(response, type: BannedEvent)
7
+ end
8
+
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ module Twitch
2
+ class BannedUsersResource < Resource
3
+
4
+ # Broadcaster ID must match the user in the OAuth token
5
+ def list(broadcaster_id:, **params)
6
+ response = get_request("moderation/banned", params: params.merge(broadcaster_id: broadcaster_id))
7
+ Collection.from_response(response, type: BannedUser)
8
+ end
9
+
10
+ end
11
+ end
@@ -0,0 +1,20 @@
1
+ module Twitch
2
+ class ChannelsResource < Resource
3
+
4
+ def get(broadcaster_id:)
5
+ User.new get_request("channels?broadcaster_id=#{broadcaster_id}").body.dig("data")[0]
6
+ end
7
+
8
+ # Requires scope: channel:manage:broadcast
9
+ def update(broadcaster_id:, **attributes)
10
+ patch_request("channels", body: attributes.merge(broadcaster_id: broadcaster_id))
11
+ end
12
+
13
+ # Requires scope: channel:read:editors
14
+ def editors(broadcaster_id:)
15
+ response = get_request("channels/editors?broadcaster_id=#{broadcaster_id}")
16
+ Collection.from_response(response, type: ChannelEditor)
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,19 @@
1
+ module Twitch
2
+ class ClipsResource < Resource
3
+
4
+ def list(**params)
5
+ raise "id, broadcaster_id or game_id is required" unless !params[:id].nil? || !params[:broadcaster_id].nil? || !params[:game_id].nil?
6
+
7
+ response = get_request("clips", params: params)
8
+ Collection.from_response(response, type: Clip)
9
+ end
10
+
11
+ # Required scope: clips:edit
12
+ def create(broadcaster_id:, **attributes)
13
+ response = post_request("clips", body: attributes.merge(broadcaster_id: broadcaster_id))
14
+
15
+ Clip.new(response.body.dig("data")[0]) if response.success?
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,22 @@
1
+ module Twitch
2
+ class CustomRewardRedemptionsResource < Resource
3
+
4
+ # Required scope: channel:read:redemptions
5
+ # Broadcaster ID must match the user in the OAuth token
6
+ def list(broadcaster_id:, reward_id:, status:, **params)
7
+ attributes = {broadcaster_id: broadcaster_id, reward_id: reward_id, status: status.upcase}
8
+ response = get_request("channel_points/custom_rewards/redemptions", params: attributes.merge(params))
9
+ Collection.from_response(response, type: CustomRewardRedemption)
10
+ end
11
+
12
+ # Currently disabled as getting this error and can't work out why
13
+ # Twitch::Error (Error 400: Your request was malformed. 'The parameter "id" was malformed: the value must be greater than or equal to 1')
14
+ # def update(broadcaster_id:, reward_id:, redemption_id:, status:)
15
+ # attributes = {broadcaster_id: broadcaster_id, reward_id: reward_id, id: redemption_id, status: status.upcase}
16
+ # response = patch_request("channel_points/custom_rewards/redemptions", body: attributes)
17
+
18
+ # CustomRewardRedemption.new(response.body.dig("data")[0]) if response.success?
19
+ # end
20
+
21
+ end
22
+ end
@@ -0,0 +1,30 @@
1
+ module Twitch
2
+ class CustomRewardsResource < Resource
3
+
4
+ # Required scope: channel:read:redemptions
5
+ # Broadcaster ID must match the user in the OAuth token
6
+ def list(broadcaster_id:, **params)
7
+ response = get_request("channel_points/custom_rewards", params: params.merge(broadcaster_id: broadcaster_id))
8
+ Collection.from_response(response, type: CustomReward)
9
+ end
10
+
11
+ def create(broadcaster_id:, title:, cost:, **params)
12
+ attributes = {broadcaster_id: broadcaster_id, title: title, cost: cost}
13
+ response = post_request("channel_points/custom_rewards", body: attributes.merge(params))
14
+
15
+ CustomReward.new(response.body.dig("data")[0]) if response.success?
16
+ end
17
+
18
+ def update(broadcaster_id:, reward_id:, **params)
19
+ attributes = {broadcaster_id: broadcaster_id, id: reward_id}
20
+ response = patch_request("channel_points/custom_rewards", body: attributes.merge(params))
21
+
22
+ CustomReward.new(response.body.dig("data")[0]) if response.success?
23
+ end
24
+
25
+ def delete(broadcaster_id:, reward_id:)
26
+ delete_request("channel_points/custom_rewards", params: {broadcaster_id: broadcaster_id, id: reward_id})
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,20 @@
1
+ module Twitch
2
+ class EmotesResource < Resource
3
+
4
+ def channel(broadcaster_id:)
5
+ response = get_request("chat/emotes?broadcaster_id=#{broadcaster_id}")
6
+ Collection.from_response(response, type: Emote)
7
+ end
8
+
9
+ def global
10
+ response = get_request("chat/emotes/global")
11
+ Collection.from_response(response, type: Emote)
12
+ end
13
+
14
+ def sets(emote_set_id:)
15
+ response = get_request("chat/emotes/set?emote_set_id=#{emote_set_id}")
16
+ Collection.from_response(response, type: Emote)
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,21 @@
1
+ module Twitch
2
+ class EventSubSubscriptionsResource < Resource
3
+
4
+ def list(**params)
5
+ response = get_request("eventsub/subscriptions", params: params)
6
+ Collection.from_response(response, type: EventSubSubscription)
7
+ end
8
+
9
+ def create(type:, version:, condition:, transport:)
10
+ attributes = {type: type, version: version, condition: condition, transport: transport}
11
+ response = post_request("eventsub/subscriptions", body: attributes)
12
+
13
+ EventSubSubscription.new(response.body.dig("data")[0]) if response.success?
14
+ end
15
+
16
+ def delete(id:)
17
+ delete_request("eventsub/subscriptions", params: {id: id})
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,20 @@
1
+ module Twitch
2
+ class GamesResource < Resource
3
+
4
+ def get_by_id(game_id:)
5
+ response = get_request("games?id=#{game_id}")
6
+ Collection.from_response(response, type: Game)
7
+ end
8
+
9
+ def get_by_name(name:)
10
+ response = get_request("games?name=#{name}")
11
+ Collection.from_response(response, type: Game)
12
+ end
13
+
14
+ def top(**params)
15
+ response = get_request("games/top", params: params)
16
+ Collection.from_response(response, type: Game)
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,12 @@
1
+ module Twitch
2
+ class GoalsResource < Resource
3
+
4
+ # Required scope: channel:read:goals
5
+ # Broadcaster ID must match the user in the OAuth token
6
+ def list(broadcaster_id:)
7
+ response = get_request("goals", params: {broadcaster_id: broadcaster_id})
8
+ Collection.from_response(response, type: Goal)
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module Twitch
2
+ class HypeTrainEventsResource < Resource
3
+
4
+ # Required scope: channel:read:hype_train
5
+ # Broadcaster ID must match the user in the OAuth token
6
+ def list(broadcaster_id:)
7
+ response = get_request("hypetrain/events", params: {broadcaster_id: broadcaster_id})
8
+ Collection.from_response(response, type: HypeTrainEvent)
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ module Twitch
2
+ class ModeratorEventsResource < Resource
3
+
4
+ # Broadcaster ID must match the user in the OAuth token
5
+ def list(broadcaster_id:, **params)
6
+ response = get_request("moderation/moderators/events", params: params.merge(broadcaster_id: broadcaster_id))
7
+ Collection.from_response(response, type: ModeratorEvent)
8
+ end
9
+
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Twitch
2
+ class ModeratorsResource < Resource
3
+
4
+ # Broadcaster ID must match the user in the OAuth token
5
+ def list(broadcaster_id:, **params)
6
+ response = get_request("moderation/moderators", params: params.merge(broadcaster_id: broadcaster_id))
7
+ Collection.from_response(response, type: Moderator)
8
+ end
9
+
10
+ end
11
+ end
@@ -0,0 +1,27 @@
1
+ module Twitch
2
+ class PollsResource < Resource
3
+
4
+ # Broadcaster ID must match the user in the OAuth token
5
+ def list(broadcaster_id:, **params)
6
+ response = get_request("polls", params: params.merge(broadcaster_id: broadcaster_id))
7
+ Collection.from_response(response, type: Poll)
8
+ end
9
+
10
+ # Broadcaster ID must match the user in the OAuth token
11
+ def create(broadcaster_id:, title:, choices:, duration:, **params)
12
+ attrs = {broadcaster_id: broadcaster_id, title: title, choices: choices, duration: duration}
13
+ response = post_request("polls", body: attrs.merge(params))
14
+
15
+ Poll.new(response.body.dig("data")[0]) if response.success?
16
+ end
17
+
18
+ # Broadcaster ID must match the user in the OAuth token
19
+ def end(broadcaster_id:, id:, status:)
20
+ attrs = {broadcaster_id: broadcaster_id, id: id, status: status.upcase}
21
+ response = patch_request("polls", body: attrs)
22
+
23
+ Poll.new(response.body.dig("data")[0]) if response.success?
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,32 @@
1
+ module Twitch
2
+ class PredictionsResource < Resource
3
+
4
+ # Broadcaster ID must match the user in the OAuth token
5
+ def list(broadcaster_id:, **params)
6
+ response = get_request("predictions", params: params.merge(broadcaster_id: broadcaster_id))
7
+
8
+ if response.body["data"]
9
+ Collection.from_response(response, type: Prediction)
10
+ else
11
+ nil
12
+ end
13
+ end
14
+
15
+ # Broadcaster ID must match the user in the OAuth token
16
+ def create(broadcaster_id:, title:, outcomes:, duration:, **params)
17
+ attrs = {broadcaster_id: broadcaster_id, title: title, outcomes: outcomes, prediction_window: duration}
18
+ response = post_request("predictions", body: attrs.merge(params))
19
+
20
+ Prediction.new(response.body.dig("data")[0]) if response.success?
21
+ end
22
+
23
+ # Broadcaster ID must match the user in the OAuth token
24
+ def end(broadcaster_id:, id:, status:, **params)
25
+ attrs = {broadcaster_id: broadcaster_id, id: id, status: status.upcase}
26
+ response = patch_request("predictions", body: attrs.merge(params))
27
+
28
+ Prediction.new(response.body.dig("data")[0]) if response.success?
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,17 @@
1
+ module Twitch
2
+ class SearchResource < Resource
3
+
4
+ def categories(query:, **params)
5
+ response = get_request("search/categories", params: params.merge(query: query))
6
+
7
+ Collection.from_response(response, type: SearchResult)
8
+ end
9
+
10
+ def channels(query:, **params)
11
+ response = get_request("search/channels", params: params.merge(query: query))
12
+
13
+ Collection.from_response(response, type: SearchResult)
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,19 @@
1
+ module Twitch
2
+ class StreamMarkersResource < Resource
3
+
4
+ # Required scope: user:read:broadcast
5
+ def list(**params)
6
+ response = get_request("streams/markers", params: params)
7
+
8
+ Collection.from_response(response, type: StreamMarker)
9
+ end
10
+
11
+ # Required scope: channel:manage:broadcast
12
+ def create(user_id:, **params)
13
+ response = post_request("streams/markers", body: params.merge(user_id: user_id))
14
+
15
+ StreamMarker.new(response.body.dig("data")[0]) if response.success?
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,47 @@
1
+ module Twitch
2
+ class StreamScheduleResource < Resource
3
+
4
+ # Broadcaster ID must match the user in the OAuth token
5
+ def list(broadcaster_id:, **params)
6
+ response = get_request("schedule", params: params.merge(broadcaster_id: broadcaster_id))
7
+
8
+ StreamSchedule.new(response.body) if response.success?
9
+ end
10
+
11
+ # Broadcaster ID must match the user in the OAuth token
12
+ def icalendar(broadcaster_id:)
13
+ response = get_request("schedule/icalendar", params: {broadcaster_id: broadcaster_id})
14
+
15
+ response.body
16
+ end
17
+
18
+ # Broadcaster ID must match the user in the OAuth token
19
+ # TODO: Allow the user to put any date format and then convert it to RFC3339
20
+ def update(broadcaster_id:, **params)
21
+ patch_request("schedule/settings", body: params.merge(broadcaster_id: broadcaster_id))
22
+ end
23
+
24
+ # Broadcaster ID must match the user in the OAuth token
25
+ def create_segment(broadcaster_id:, start_time:, timezone:, duration:, is_recurring:, **params)
26
+ attrs = {broadcaster_id: broadcaster_id, start_time: start_time, duration: duration, timezone: timezone, is_recurring: is_recurring}
27
+ response = post_request("schedule/segment", body: attrs.merge(params))
28
+
29
+ StreamSchedule.new(response.body) if response.success?
30
+ end
31
+
32
+ # Broadcaster ID must match the user in the OAuth token
33
+ def update_segment(broadcaster_id:, id:, **params)
34
+ attrs = {broadcaster_id: broadcaster_id, id: id}
35
+ response = patch_request("schedule/segment", body: attrs.merge(params))
36
+
37
+ StreamSchedule.new(response.body) if response.success?
38
+ end
39
+
40
+ # Broadcaster ID must match the user in the OAuth token
41
+ def delete_segment(broadcaster_id:, id:)
42
+ attrs = {broadcaster_id: broadcaster_id, id: id}
43
+ delete_request("schedule/segment", params: attrs)
44
+ end
45
+
46
+ end
47
+ end
@@ -0,0 +1,19 @@
1
+ module Twitch
2
+ class StreamsResource < Resource
3
+
4
+ def list(**params)
5
+ response = get_request("streams", params: params)
6
+
7
+ Collection.from_response(response, type: Stream)
8
+ end
9
+
10
+ # Required scope: user:read:follows
11
+ # User ID must match the user in the OAuth token
12
+ def followed(user_id:, **params)
13
+ response = get_request("streams/followed", params: params.merge(user_id: user_id))
14
+
15
+ Collection.from_response(response, type: Stream)
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,73 @@
1
+ module Twitch
2
+ class SubscriptionsResource < Resource
3
+
4
+ # Get all subscriptions for a broadcaster
5
+ # Broadcaster ID must match the user in the OAuth token
6
+ # Required scope: channel:read:subscriptions
7
+ def list(broadcaster_id:, **params)
8
+ response = get_request("subscriptions", params: params.merge(broadcaster_id: broadcaster_id))
9
+ Collection.from_response(response, type: Subscription)
10
+ end
11
+
12
+ # Checks if a User is subscribed to a Broadcaster
13
+ # If 404 then the user is not subscribed
14
+ # User ID must match the user in the OAuth token
15
+ # Required scope: user:read:subscriptions
16
+ def is_subscribed(broadcaster_id:, user_id:, **params)
17
+ attrs = {broadcaster_id: broadcaster_id, user_id: user_id}
18
+ response = get_request("subscriptions/user", params: attrs.merge(params))
19
+ Collection.from_response(response, type: Subscription)
20
+ end
21
+
22
+ # Calculate the number of Subscribers & Subscriber Points a broadcaster has
23
+ # Broadcaster ID must match the user in the OAuth token
24
+ # Required scope: channel:read:subscriptions
25
+ def calculate(broadcaster_id:, remove_count: 0, remove_points: 0)
26
+ calculate_subs(broadcaster_id: broadcaster_id, remove_count: remove_count, remove_points: remove_points)
27
+ end
28
+
29
+ private
30
+
31
+ def get_subscriptions(broadcaster_id:)
32
+ subs = []
33
+ cursor = nil
34
+ count = 1
35
+
36
+ while count > 0
37
+ sub_response = list(broadcaster_id: broadcaster_id, first: 100, after: cursor)
38
+
39
+ subs += sub_response.data
40
+
41
+ cursor = sub_response.cursor
42
+ count = sub_response.total
43
+ end
44
+
45
+ return subs
46
+ end
47
+
48
+ def calculate_subs(broadcaster_id:, remove_count:, remove_points:)
49
+ subs = get_subscriptions(broadcaster_id: broadcaster_id)
50
+
51
+ count = 0
52
+ points = 0
53
+
54
+ if !subs.empty? && subs.count >= 1
55
+ subs.each do |sub|
56
+ # We don't want to add the broadcaster into the count
57
+ next if sub.user_id.to_s == broadcaster_id.to_s
58
+
59
+ count += 1
60
+ points += 1 if sub.tier == "1000"
61
+ points += 2 if sub.tier == "2000"
62
+ points += 6 if sub.tier == "3000"
63
+ end
64
+
65
+ count = (count - remove_count)
66
+ points = (points - remove_points)
67
+ end
68
+
69
+ SubscriptionCount.new(count: count, points: points)
70
+ end
71
+
72
+ end
73
+ end
@@ -0,0 +1,20 @@
1
+ module Twitch
2
+ class TagsResource < Resource
3
+
4
+ def list(**params)
5
+ response = get_request("tags/streams", params: params)
6
+ Collection.from_response(response, type: Tag)
7
+ end
8
+
9
+ def stream(broadcaster_id:, **params)
10
+ response = get_request("streams/tags", params: params.merge(broadcaster_id: broadcaster_id))
11
+ Collection.from_response(response, type: Tag)
12
+ end
13
+
14
+ # Required scope: channel:manage:broadcast
15
+ def replace(broadcaster_id:, **params)
16
+ put_request("streams/tags", body: params.merge(broadcaster_id: broadcaster_id))
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,54 @@
1
+ module Twitch
2
+ class UsersResource < Resource
3
+
4
+ def get_by_id(user_id:)
5
+ User.new get_request("users/?id=#{user_id}").body.dig("data")[0]
6
+ end
7
+
8
+ def get_by_username(username:)
9
+ User.new get_request("users/?login=#{username}").body.dig("data")[0]
10
+ end
11
+
12
+ # Updates the current users description
13
+ # Required scope: user:edit
14
+ def update(description:)
15
+ response = put_request("users", body: {description: description})
16
+ User.new response.body.dig("data")[0]
17
+ end
18
+
19
+ def follows(**params)
20
+ raise "from_id or to_id is required" unless !params[:from_id].nil? || !params[:to_id].nil?
21
+
22
+ response = get_request("users/follows", params: params)
23
+ Collection.from_response(response, type: FollowedUser)
24
+ end
25
+
26
+ # Required scope: user:read:blocked_users
27
+ def blocks(broadcaster_id:, **params)
28
+ response = get_request("users/blocks?broadcaster_id=#{broadcaster_id}", params: params)
29
+ Collection.from_response(response, type: BlockedUser)
30
+ end
31
+
32
+ # Required scope: user:manage:blocked_users
33
+ def block_user(target_user_id:, **attributes)
34
+ put_request("users/blocks?target_user_id=#{target_user_id}", body: attributes)
35
+ end
36
+
37
+ # Required scope: user:manage:blocked_users
38
+ def unblock_user(target_user_id:)
39
+ delete_request("users/blocks?target_user_id=#{target_user_id}")
40
+ end
41
+
42
+ # A quick method to see if a user is following a channel
43
+ def following?(from_id:, to_id:)
44
+ response = get_request("users/follows", params: {from_id: from_id, to_id: to_id})
45
+
46
+ if response.body["data"].empty?
47
+ false
48
+ else
49
+ true
50
+ end
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,17 @@
1
+ module Twitch
2
+ class VideosResource < Resource
3
+
4
+ def list(**params)
5
+ raise "id, user_id or game_id is required" unless !params[:id].nil? || !params[:user_id].nil? || !params[:game_id].nil?
6
+
7
+ response = get_request("videos", params: params)
8
+ Collection.from_response(response, type: Video)
9
+ end
10
+
11
+ # Required scope: channel:manage:videos
12
+ # def delete(video_id:)
13
+ # delete_request("videos?id=#{video_id}")
14
+ # end
15
+
16
+ end
17
+ end
@@ -1,3 +1,3 @@
1
1
  module Twitch
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.0"
3
3
  end