twitchrb 0.1.1 → 0.2.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.
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