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.
- 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
|
@@ -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
|
data/lib/twitch/version.rb
CHANGED