uscreen_api 0.1.2 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 55f8484643d8a37813e8891451aff82a54279c02d6a56f4a574083f2d1df2ebd
4
- data.tar.gz: 56fecb97380306860c12babb89b541bae88cfa1f90b9aed2aa367a0a66ca2ad7
3
+ metadata.gz: c2726704dcbd621602f5472647621df43e074ff09ccb8d9d45498a49ba4903a3
4
+ data.tar.gz: 8d94928a74bba4381665c2ebd9bc73d8dcb04204a8e6c72c1e6ba73546300a34
5
5
  SHA512:
6
- metadata.gz: b849a8f6cd490c836a02fdd588eaa2599540eb33be38159a98ed342113a675b7f02db79e3e5c62413f51b535adc423d0f3471b2a5179855d76e18764c9e2f421
7
- data.tar.gz: 917771f0b4044c8c8fe0d9af12e42efe9efd296ae0e4a8c9eb8f54da8e43faa4703b7cda37bb57f898ba64aa63624b2f0fb6fc4b647e49210698f1ee9b242328
6
+ metadata.gz: cbca6b40d77f39a6f104b458e057da40995b81953a5bc419ac7ec0feaa4fea1468313cfb656a64fa434fd0b373cda970faf451838bcc2ac5391734740b6c033c
7
+ data.tar.gz: d52532e0437f781e3e22c907f3b876fdba1f14c8660af61f7ebdf6532f6d4e3821b1deeaf5fbf59f0e57ec03a139f04f8c5aed73dff560a648e0388ce095b7a2
data/README.md CHANGED
@@ -15,7 +15,35 @@ gem install uscreen_api
15
15
 
16
16
  ## Usage
17
17
 
18
- TODO: Write usage instructions here
18
+ ```ruby
19
+ require "uscreen_api"
20
+
21
+ client = UscreenAPI::Client.new(api_key: ENV["USCREEN_API_KEY"])
22
+
23
+ client.customers.list(page: 1)
24
+ client.customers.create(email: "joe@example.com", name: "Joe Shmoe", skip_invite: true)
25
+ client.customers.get(id: "joe@example.com")
26
+ client.customers.grant_access(id: 123, product_id: 456, product_type: "recurring")
27
+ client.customers.create_subscription(id: 123, product_id: 789)
28
+ client.contents.list(content_type: "video", include: "author")
29
+ client.analytics.video_views(user_id: 123)
30
+ ```
31
+
32
+ Supported resources, matching the [Publisher API](https://www.uscreen.io/api/publisher.html):
33
+
34
+ | Resource | Methods |
35
+ | --- | --- |
36
+ | `customers` | `list`, `create`, `get`, `update`, `tokenized_url`, `accesses`, `access`, `grant_access`, `revoke_access`, `subscription`, `create_subscription`, `cancel_subscription` |
37
+ | `groups` | `list`, `create`, `delete`, `members`, `add_member`, `remove_member` |
38
+ | `contents` | `list`, `get`, `playlist_items`, `playlist_item`, `publish`, `unpublish`, `schedule` |
39
+ | `programs` (legacy alias of contents) | `list`, `get`, `chapters`, `chapter` |
40
+ | `videos` | `list`, `get` |
41
+ | `offers` | `list`, `get` |
42
+ | `invoices` | `list`, `get` |
43
+ | `email_topics` | `list` |
44
+ | `analytics` | `video_views`, `total_watch_time`, `video_views_summary` |
45
+
46
+ Errors raise subclasses of `UscreenAPI::Errors::Error`: `Unauthorized` (401), `NotFound` (404), `UnprocessableEntity` (422). Customer endpoints raise `UserNotFound` / `UserNotCreated`, which subclass `NotFound` / `UnprocessableEntity`.
19
47
 
20
48
  ## Development
21
49
 
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UscreenAPI
4
+ class Analytics < Base
5
+ PATH = "analytics/videos/views"
6
+
7
+ # Get details on video views for a user, video, collection or live event. Default range: last 12 months.
8
+ # @param page [Integer] Page number
9
+ # @param per_page [Integer] Number of results per page (default 10, max 100)
10
+ # @param user_id [String] User ID or Email
11
+ # @param content_id [String] Video, Collection or Live Event ID
12
+ # @param from [String] Starting date and time, formatted in RFC 3339. Must be within last 12 months. Example: 2023-01-01T00:00:00Z
13
+ # @param to [String] Ending date and time, formatted in RFC 3339. Example: 2023-01-01T00:00:00Z
14
+ def video_views(page: nil, per_page: nil, user_id: nil, content_id: nil, from: nil, to: nil)
15
+ request(:get, PATH, params: {
16
+ page: page,
17
+ per_page: per_page,
18
+ user_id: user_id,
19
+ content_id: content_id,
20
+ from: from,
21
+ to: to
22
+ })
23
+ end
24
+
25
+ # Get the total video watch time for a user, video, collection or live event. Default range: last 12 months.
26
+ # @param user_id [String] User ID or Email
27
+ # @param content_id [String] Video, Collection or Live Event ID
28
+ # @param from [String] Starting date and time, formatted in RFC 3339. Must be within last 12 months. Example: 2023-01-01T00:00:00Z
29
+ # @param to [String] Ending date and time, formatted in RFC 3339. Example: 2023-01-01T00:00:00Z
30
+ def total_watch_time(user_id: nil, content_id: nil, from: nil, to: nil)
31
+ request(:get, "#{PATH}/total_watch_time", params: {user_id: user_id, content_id: content_id, from: from, to: to})
32
+ end
33
+
34
+ # Get video view counts and total watch time grouped by user and video. Default range: last 12 months.
35
+ # @param page [Integer] Page number
36
+ # @param per_page [Integer] Number of results per page (default 50, max 100)
37
+ # @param from [String] Starting date and time, formatted in RFC 3339. Must be within last 12 months. Example: 2023-01-01T00:00:00Z
38
+ # @param to [String] Ending date and time, formatted in RFC 3339. Example: 2023-01-01T00:00:00Z
39
+ def video_views_summary(page: nil, per_page: nil, from: nil, to: nil)
40
+ request(:get, "#{PATH}/summary", params: {page: page, per_page: per_page, from: from, to: to})
41
+ end
42
+ end
43
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module UscreenAPI
2
4
  class Base
3
5
  attr_reader :client
@@ -8,11 +10,37 @@ module UscreenAPI
8
10
 
9
11
  private
10
12
 
13
+ # Perform a request and return the parsed response body.
14
+ # Keys with nil values are dropped from params and body so optional arguments are only sent when given.
15
+ def request(method, path, params: {}, body: nil)
16
+ response = client.connection.public_send(method, path) do |req|
17
+ req.params.update(compact(params))
18
+ req.body = compact(body) if body
19
+ end
20
+
21
+ handle_errors(response.status, response.body)
22
+
23
+ response.body
24
+ end
25
+
26
+ def compact(hash)
27
+ hash.reject { |_, value| value.nil? }
28
+ end
29
+
30
+ def not_found_error
31
+ UscreenAPI::Errors::NotFound
32
+ end
33
+
34
+ def unprocessable_entity_error
35
+ UscreenAPI::Errors::UnprocessableEntity
36
+ end
37
+
11
38
  def handle_errors(status, body)
12
39
  case status
13
40
  when 401 then raise UscreenAPI::Errors::Unauthorized.new(body)
14
- when 404 then raise UscreenAPI::Errors::UserNotFound.new(body)
15
- when 422 then raise UscreenAPI::Errors::UserNotCreated.new(body)
41
+ when 404 then raise not_found_error.new(body)
42
+ when 422 then raise unprocessable_entity_error.new(body)
43
+ when 400..599 then raise UscreenAPI::Errors::Error.new(body)
16
44
  end
17
45
  end
18
46
  end
@@ -4,20 +4,55 @@ require "faraday"
4
4
 
5
5
  module UscreenAPI
6
6
  class Client
7
- attr_reader :api_key
7
+ attr_reader :api_key, :adapter
8
8
 
9
9
  BASE_URL = "https://www.uscreen.io/publisher_api/v1/"
10
10
 
11
- def initialize(api_key:)
11
+ # @param api_key [String] Publisher API key
12
+ # @param adapter [Symbol, Array] Faraday adapter, optionally followed by its arguments. Example: [:test, stubs]
13
+ def initialize(api_key:, adapter: Faraday.default_adapter)
12
14
  @api_key = api_key
15
+ @adapter = adapter
16
+ end
17
+
18
+ def analytics
19
+ @analytics ||= UscreenAPI::Analytics.new(client: self)
20
+ end
21
+
22
+ def contents
23
+ @contents ||= UscreenAPI::Contents.new(client: self)
13
24
  end
14
25
 
15
26
  def customers
16
27
  @customers ||= UscreenAPI::Customers.new(client: self)
17
28
  end
18
29
 
30
+ def email_topics
31
+ @email_topics ||= UscreenAPI::EmailTopics.new(client: self)
32
+ end
33
+
34
+ def groups
35
+ @groups ||= UscreenAPI::Groups.new(client: self)
36
+ end
37
+
38
+ def invoices
39
+ @invoices ||= UscreenAPI::Invoices.new(client: self)
40
+ end
41
+
42
+ def offers
43
+ @offers ||= UscreenAPI::Offers.new(client: self)
44
+ end
45
+
46
+ def programs
47
+ @programs ||= UscreenAPI::Programs.new(client: self)
48
+ end
49
+
50
+ def videos
51
+ @videos ||= UscreenAPI::Videos.new(client: self)
52
+ end
53
+
19
54
  def connection
20
- @connection = Faraday.new(
55
+ @connection ||= Faraday.new(
21
56
  url: BASE_URL,
22
57
  headers: {
23
58
  "Content-Type": "application/json",
@@ -26,6 +61,7 @@ module UscreenAPI
26
61
  ) do |f|
27
62
  f.request(:json)
28
63
  f.response(:json)
64
+ f.adapter(*Array(adapter))
29
65
  end
30
66
  end
31
67
  end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UscreenAPI
4
+ class Contents < Base
5
+ PATH = "contents"
6
+
7
+ # Get paginated list of contents (videos, collections and live events)
8
+ # @param page [Integer] Page number
9
+ # @param include [String] Comma-separated list of relationships to include. Available relationships: author.
10
+ # @param from [String] Starting date and time for the filter range, formatted in RFC 3339. Example: 2023-01-01T00:00:00Z
11
+ # @param to [String] Ending date and time for the filter range, formatted in RFC 3339. Example: 2023-01-01T00:00:00Z
12
+ # @param content_type [String] Filter by content type. Can be collection|live_event|video
13
+ def list(page: nil, include: nil, from: nil, to: nil, content_type: nil)
14
+ request(:get, PATH, params: {page: page, include: include, from: from, to: to, content_type: content_type})
15
+ end
16
+
17
+ # Get content information (video, collection or live event)
18
+ # @param id [String] Content ID
19
+ # @param include [String] Comma-separated list of relationships to include. Available relationships: author.
20
+ def get(id:, include: nil)
21
+ request(:get, "#{PATH}/#{id}", params: {include: include})
22
+ end
23
+
24
+ # Get list of playlist items (formerly known as chapters) and file resources
25
+ # @param id [String] Content ID
26
+ def playlist_items(id:)
27
+ request(:get, "#{PATH}/#{id}/playlist_items")
28
+ end
29
+
30
+ # Get a playlist item (formerly known as chapter)
31
+ # @param id [String] Content ID
32
+ # @param playlist_item_id [String] Playlist item ID
33
+ def playlist_item(id:, playlist_item_id:)
34
+ request(:get, "#{PATH}/#{id}/playlist_items/#{playlist_item_id}")
35
+ end
36
+
37
+ # Publish a video, collection or live event
38
+ # @param id [String] Content ID
39
+ # @param event_launch_datetime [String] Live events only. Launch date and time in the future, formatted in RFC 3339. Example: 2025-06-01T12:00:00Z
40
+ def publish(id:, event_launch_datetime: nil)
41
+ request(:post, "#{PATH}/#{id}/visibility/publish", params: {event_launch_datetime: event_launch_datetime})
42
+ end
43
+
44
+ # Unpublish a video, collection or live event
45
+ # @param id [String] Content ID
46
+ def unpublish(id:)
47
+ request(:post, "#{PATH}/#{id}/visibility/unpublish")
48
+ end
49
+
50
+ # Schedule a video or collection for future publication
51
+ # @param id [String] Content ID
52
+ # @param scheduled_datetime [String] Publication date and time in the future, formatted in RFC 3339. Example: 2025-06-01T12:00:00Z
53
+ # @param schedule_published [Boolean] Allow scheduling content that is currently published. It will be unpublished and scheduled.
54
+ def schedule(id:, scheduled_datetime:, schedule_published: nil)
55
+ request(:post, "#{PATH}/#{id}/visibility/schedule", params: {
56
+ scheduled_datetime: scheduled_datetime,
57
+ schedule_published: schedule_published
58
+ })
59
+ end
60
+ end
61
+ end
@@ -15,28 +15,21 @@ module UscreenAPI
15
15
  to: nil,
16
16
  date_field: nil
17
17
  )
18
- response = client.connection.get(PATH) do |req|
19
- req.params = {}
20
-
21
- req.params["page"] = page if page
22
- req.params["from"] = from if from
23
- req.params["to"] = to if to
24
- req.params["date_field"] = date_field if date_field
25
- end
26
-
27
- handle_errors(response.status, response.body)
28
-
29
- response.body
18
+ request(:get, PATH, params: {page: page, from: from, to: to, date_field: date_field})
30
19
  end
31
20
 
32
21
  # Invite a new customer
33
- # @param email [String] Customer email
22
+ # @param email [String] Customer email. Should be unique
34
23
  # @param name [String] Customer name
35
- # @param password [String] Customer password
36
- # @param payment_user_id [String] Payment user ID
37
- # @param skip_invite [Boolean] Skip invite email
38
- # @param opted_in_for_news_and_updates [Boolean] Opted in for news and updates
39
- # @param custom_fields [Hash] Custom fields
24
+ # @param password [String] Password (8 characters minimum). Generated automatically if blank.
25
+ # @param payment_user_id [String] Stripe User ID, for matching Stripe accounts
26
+ # @param skip_invite [Boolean] Skip the platform invite email
27
+ # @param opted_in_for_news_and_updates [Boolean] Opted in for news and update emails
28
+ # @param opted_in_for_community_updates [Boolean] Opted in for community update emails
29
+ # @param legacy_id [String] External identifier used to reference this customer in third-party systems
30
+ # @param tags [Array<String>] Tag names to assign to the customer (lowercase letters, numbers and dashes)
31
+ # @param unsubscribed_topic_ids [Array<Integer>] Email topic IDs to unsubscribe the customer from
32
+ # @param custom_fields [Hash] Custom fields. Example: { field_1: "value" }
40
33
  def create(
41
34
  email:,
42
35
  name:,
@@ -44,71 +37,73 @@ module UscreenAPI
44
37
  payment_user_id: nil,
45
38
  skip_invite: nil,
46
39
  opted_in_for_news_and_updates: nil,
40
+ opted_in_for_community_updates: nil,
41
+ legacy_id: nil,
42
+ tags: nil,
43
+ unsubscribed_topic_ids: nil,
47
44
  custom_fields: {}
48
45
  )
49
- response = client.connection.post(PATH) do |req|
50
- req.body = {
51
- email: email,
52
- name: name
53
- }
54
- req.body["password"] = password if password
55
- req.body["payment_user_id"] = payment_user_id if payment_user_id
56
- req.body["skip_invite"] = skip_invite if skip_invite
57
- req.body["opted_in_for_news_and_updates"] = opted_in_for_news_and_updates if opted_in_for_news_and_updates
58
-
59
- custom_fields.each { |key, value| req.body[key] = value } if custom_fields.any?
60
- end
61
-
62
- handle_errors(response.status, response.body)
63
-
64
- response.body
46
+ request(:post, PATH, body: {
47
+ email: email,
48
+ name: name,
49
+ password: password,
50
+ payment_user_id: payment_user_id,
51
+ skip_invite: skip_invite,
52
+ opted_in_for_news_and_updates: opted_in_for_news_and_updates,
53
+ opted_in_for_community_updates: opted_in_for_community_updates,
54
+ legacy_id: legacy_id,
55
+ tags: tags,
56
+ unsubscribed_topic_ids: unsubscribed_topic_ids,
57
+ **custom_fields
58
+ })
65
59
  end
66
60
 
67
61
  # Get a customer information
68
62
  # @param id [Integer] Customer ID or Email
69
63
  def get(id:)
70
- response = client.connection.get("#{PATH}/#{id}")
71
-
72
- handle_errors(response.status, response.body)
73
-
74
- response.body
64
+ request(:get, "#{PATH}/#{id}")
75
65
  end
76
66
 
77
67
  # Update a customer information
78
68
  # @param id [Integer] Customer ID or Email
79
69
  # @param email [String] New customer email
80
70
  # @param name [String] New customer name
81
- # @param password [String] New customer password
82
- # @param custom_fields [Hash] Custom fields
71
+ # @param password [String] New customer password (8 characters minimum)
72
+ # @param payment_user_id [String] Stripe Customer ID
73
+ # @param opted_in_for_news_and_updates [Boolean] Receive marketing emails
74
+ # @param opted_in_for_community_updates [Boolean] Receive community update emails
75
+ # @param tags [Array<String>] Tag names to assign to the customer. Replaces existing tags.
76
+ # @param unsubscribed_topic_ids [Array<Integer>] Email topic IDs to unsubscribe the customer from
77
+ # @param custom_fields [Hash] Custom fields. Example: { field_1: "value" }
83
78
  def update(
84
79
  id:,
85
80
  email: nil,
86
81
  name: nil,
87
82
  password: nil,
83
+ payment_user_id: nil,
84
+ opted_in_for_news_and_updates: nil,
85
+ opted_in_for_community_updates: nil,
86
+ tags: nil,
87
+ unsubscribed_topic_ids: nil,
88
88
  custom_fields: {}
89
89
  )
90
- response = client.connection.put("#{PATH}/#{id}") do |req|
91
- req.body = {}
92
-
93
- req.body["email"] = email if email
94
- req.body["name"] = name if name
95
- req.body["password"] = password if password
96
-
97
- custom_fields.each { |key, value| req.body[key] = value } if custom_fields.any?
98
- end
99
-
100
- handle_errors(response.status, response.body)
101
-
102
- response.body
90
+ request(:put, "#{PATH}/#{id}", body: {
91
+ email: email,
92
+ name: name,
93
+ password: password,
94
+ payment_user_id: payment_user_id,
95
+ opted_in_for_news_and_updates: opted_in_for_news_and_updates,
96
+ opted_in_for_community_updates: opted_in_for_community_updates,
97
+ tags: tags,
98
+ unsubscribed_topic_ids: unsubscribed_topic_ids,
99
+ **custom_fields
100
+ })
103
101
  end
104
102
 
105
103
  # Generates a Single Sign-On link for a customer
106
104
  # @param id [Integer] Customer ID or Email
107
105
  def tokenized_url(id:)
108
- response = client.connection.post("#{PATH}/#{id}/tokenized_url")
109
- handle_errors(response.status, response.body)
110
-
111
- response.body
106
+ request(:post, "#{PATH}/#{id}/tokenized_url")
112
107
  end
113
108
 
114
109
  # Get paginated list of accesses for a customer
@@ -122,37 +117,38 @@ module UscreenAPI
122
117
  from: nil,
123
118
  to: nil
124
119
  )
125
- response = client.connection.get("#{PATH}/#{id}/accesses")
126
- handle_errors(response.status, response.body)
120
+ request(:get, "#{PATH}/#{id}/accesses", params: {page: page, from: from, to: to})
121
+ end
127
122
 
128
- response.body
123
+ # Get access by ID
124
+ # @param id [Integer] Customer ID or Email
125
+ # @param access_id [Integer] Access ID
126
+ def access(id:, access_id:)
127
+ request(:get, "#{PATH}/#{id}/accesses/#{access_id}")
129
128
  end
130
129
 
131
130
  # Grant access to a customer
132
131
  # @param id [Integer] Customer ID or Email
133
132
  # @param product_id [Integer] Product ID
134
133
  # @param product_type [String] Uscreen system product type. Can be a program|recurring|rent|freebie|fixed_price
135
- # @param perform_action_at [String] Seconds since the Epoch. Next perform action needed in case of rent or recurring product types. System will add next due automatically in case of a blank field. example: 2024-07-05T13:47:52Z
134
+ # @param perform_action_at [String] Next perform action needed in case of rent or recurring product types. System will add next due automatically in case of a blank field. Omit when with_manual_billing is true. Example: 2024-07-05T13:47:52Z
136
135
  # @param with_manual_billing [Boolean] Allows you to process billing outside the Uscreen platform. Default false.
136
+ # @param skip_automations [Boolean] Skip automation enrollment (e.g. bundle_assigned). Default false.
137
137
  def grant_access(
138
138
  id:,
139
139
  product_id:,
140
140
  product_type: nil,
141
141
  perform_action_at: nil,
142
- with_manual_billing: false
142
+ with_manual_billing: false,
143
+ skip_automations: nil
143
144
  )
144
- response = client.connection.post("#{PATH}/#{id}/accesses") do |req|
145
- req.body = {
146
- product_id: product_id,
147
- with_manual_billing: with_manual_billing
148
- }
149
- req.body["product_type"] = product_type if product_type
150
- req.body["perform_action_at"] = perform_action_at if perform_action_at
151
- end
152
-
153
- handle_errors(response.status, response.body)
154
-
155
- response.body
145
+ request(:post, "#{PATH}/#{id}/accesses", body: {
146
+ product_id: product_id,
147
+ product_type: product_type,
148
+ perform_action_at: perform_action_at,
149
+ with_manual_billing: with_manual_billing,
150
+ skip_automations: skip_automations
151
+ })
156
152
  end
157
153
 
158
154
  # Revoke access by ID
@@ -162,10 +158,56 @@ module UscreenAPI
162
158
  id:,
163
159
  access_id:
164
160
  )
165
- response = client.connection.delete("#{PATH}/#{id}/accesses/#{access_id}")
166
- handle_errors(response.status, response.body)
161
+ request(:delete, "#{PATH}/#{id}/accesses/#{access_id}")
162
+ end
163
+
164
+ # Get a customer's active subscription. Returns nil if the customer has no active subscription.
165
+ # @param id [Integer] Customer ID or Email
166
+ def subscription(id:)
167
+ request(:get, "#{PATH}/#{id}/subscription")
168
+ end
169
+
170
+ # Create a subscription for a customer
171
+ # @param id [Integer] Customer ID or Email
172
+ # @param product_id [Integer] Subscription plan ID
173
+ # @param with_manual_billing [Boolean] Process billing outside the Uscreen platform. Default false.
174
+ # @param perform_action_at [Integer] Unix timestamp for the next billing/renewal date. Omit when with_manual_billing is true.
175
+ # @param currency [String] Three-letter currency code (ISO 4217). Must be one of the store's configured currencies.
176
+ # @param cover_fees [Boolean] Add transaction fees to the subscription price, covered by the customer
177
+ # @param skip_automations [Boolean] Skip automation enrollment (e.g. subscription_assigned). Default false.
178
+ def create_subscription(
179
+ id:,
180
+ product_id:,
181
+ with_manual_billing: nil,
182
+ perform_action_at: nil,
183
+ currency: nil,
184
+ cover_fees: nil,
185
+ skip_automations: nil
186
+ )
187
+ request(:post, "#{PATH}/#{id}/subscription", body: {
188
+ product_id: product_id,
189
+ with_manual_billing: with_manual_billing,
190
+ perform_action_at: perform_action_at,
191
+ currency: currency,
192
+ cover_fees: cover_fees,
193
+ skip_automations: skip_automations
194
+ })
195
+ end
196
+
197
+ # Cancel a customer's active subscription
198
+ # @param id [Integer] Customer ID or Email
199
+ def cancel_subscription(id:)
200
+ request(:delete, "#{PATH}/#{id}/subscription")
201
+ end
202
+
203
+ private
204
+
205
+ def not_found_error
206
+ UscreenAPI::Errors::UserNotFound
207
+ end
167
208
 
168
- response.body
209
+ def unprocessable_entity_error
210
+ UscreenAPI::Errors::UserNotCreated
169
211
  end
170
212
  end
171
213
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UscreenAPI
4
+ class EmailTopics < Base
5
+ PATH = "email_topics"
6
+
7
+ # Get the list of email topics
8
+ # @param page [Integer] Page number
9
+ def list(page: nil)
10
+ request(:get, PATH, params: {page: page})
11
+ end
12
+ end
13
+ end
@@ -1,9 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module UscreenAPI::Errors
4
- class UserNotFound < StandardError; end
4
+ class Error < StandardError; end
5
5
 
6
- class UserNotCreated < StandardError; end
6
+ class Unauthorized < Error; end
7
7
 
8
- class Unauthorized < StandardError; end
8
+ class NotFound < Error; end
9
+
10
+ class UnprocessableEntity < Error; end
11
+
12
+ # Raised by customer endpoints. Kept for backwards compatibility.
13
+ class UserNotFound < NotFound; end
14
+
15
+ class UserNotCreated < UnprocessableEntity; end
9
16
  end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UscreenAPI
4
+ class Groups < Base
5
+ PATH = "groups"
6
+
7
+ # Get paginated list of groups
8
+ # @param page [Integer] Page number
9
+ # @param from [String] Starting date and time for the filter range, formatted in RFC 3339. Example: 2023-01-01T00:00:00Z
10
+ # @param to [String] Ending date and time for the filter range, formatted in RFC 3339. Example: 2023-01-01T00:00:00Z
11
+ # @param date_field [String] Date field to filter by. Available fields: created_at, updated_at. Default: created_at.
12
+ def list(page: nil, from: nil, to: nil, date_field: nil)
13
+ request(:get, PATH, params: {page: page, from: from, to: to, date_field: date_field})
14
+ end
15
+
16
+ # Create a new group
17
+ # @param name [String] Group name
18
+ # @param billing_email [String] Billing email for the group
19
+ # @param plan_id [Integer] Subscription Plan ID associated with the group
20
+ # @param number_of_seats [Integer] Number of seats in the group. No seat limit if not provided.
21
+ def create(name:, billing_email:, plan_id:, number_of_seats: nil)
22
+ request(:post, PATH, body: {
23
+ name: name,
24
+ billing_email: billing_email,
25
+ plan_id: plan_id,
26
+ number_of_seats: number_of_seats
27
+ })
28
+ end
29
+
30
+ # Delete a group
31
+ # @param id [Integer] Group ID
32
+ def delete(id:)
33
+ request(:delete, "#{PATH}/#{id}")
34
+ end
35
+
36
+ # Get paginated list of group members
37
+ # @param id [Integer] Group ID
38
+ # @param page [Integer] Page number
39
+ # @param from [String] Starting date and time for the filter range, formatted in RFC 3339. Example: 2023-01-01T00:00:00Z
40
+ # @param to [String] Ending date and time for the filter range, formatted in RFC 3339. Example: 2023-01-01T00:00:00Z
41
+ # @param date_field [String] Date field to filter by. Available fields: created_at, updated_at. Default: created_at.
42
+ def members(id:, page: nil, from: nil, to: nil, date_field: nil)
43
+ request(:get, "#{PATH}/#{id}/members", params: {page: page, from: from, to: to, date_field: date_field})
44
+ end
45
+
46
+ # Add a member to a group
47
+ # @param id [Integer] Group ID
48
+ # @param email [String] Member's email address
49
+ # @param name [String] Member's full name
50
+ # @param role [String] Member's role in the group. Can be member|manager
51
+ # @param skip_automations [Boolean] Skip automation enrollment (e.g. lead_created). Default false.
52
+ def add_member(id:, email:, name:, role: "member", skip_automations: nil)
53
+ request(:post, "#{PATH}/#{id}/members", body: {
54
+ email: email,
55
+ name: name,
56
+ role: role,
57
+ skip_automations: skip_automations
58
+ })
59
+ end
60
+
61
+ # Remove a member from a group
62
+ # @param id [Integer] Group ID
63
+ # @param user_id [Integer] User ID
64
+ def remove_member(id:, user_id:)
65
+ request(:delete, "#{PATH}/#{id}/members/#{user_id}")
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UscreenAPI
4
+ class Invoices < Base
5
+ PATH = "invoices"
6
+
7
+ # Get paginated list of invoices
8
+ # @param page [Integer] Page number
9
+ # @param from [String] Starting date and time for the filter range, formatted in RFC 3339. Example: 2023-01-01T00:00:00Z
10
+ # @param to [String] Ending date and time for the filter range, formatted in RFC 3339. Example: 2023-01-01T00:00:00Z
11
+ # @param date_field [String] Date field to filter by. Available fields: created_at, updated_at. Default: created_at.
12
+ def list(page: nil, from: nil, to: nil, date_field: nil)
13
+ request(:get, PATH, params: {page: page, from: from, to: to, date_field: date_field})
14
+ end
15
+
16
+ # Get invoice by ID
17
+ # @param id [String] Invoice ID
18
+ def get(id:)
19
+ request(:get, "#{PATH}/#{id}")
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UscreenAPI
4
+ class Offers < Base
5
+ PATH = "offers"
6
+
7
+ # Get paginated list of offers
8
+ # @param page [Integer] Page number
9
+ # @param from [String] Starting date and time for the filter range, formatted in RFC 3339. Example: 2023-01-01T00:00:00Z
10
+ # @param to [String] Ending date and time for the filter range, formatted in RFC 3339. Example: 2023-01-01T00:00:00Z
11
+ def list(page: nil, from: nil, to: nil)
12
+ request(:get, PATH, params: {page: page, from: from, to: to})
13
+ end
14
+
15
+ # Get an offer information
16
+ # @param id [String] Offer ID
17
+ def get(id:)
18
+ request(:get, "#{PATH}/#{id}")
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UscreenAPI
4
+ # Programs are the legacy name for contents. Prefer UscreenAPI::Contents.
5
+ class Programs < Base
6
+ PATH = "programs"
7
+
8
+ # Get paginated list of programs
9
+ # @param page [Integer] Page number
10
+ # @param include [String] Comma-separated list of relationships to include. Available relationships: author.
11
+ # @param from [String] Starting date and time for the filter range, formatted in RFC 3339. Example: 2023-01-01T00:00:00Z
12
+ # @param to [String] Ending date and time for the filter range, formatted in RFC 3339. Example: 2023-01-01T00:00:00Z
13
+ # @param content_type [String] Filter by content type. Can be collection|live_event|video
14
+ def list(page: nil, include: nil, from: nil, to: nil, content_type: nil)
15
+ request(:get, PATH, params: {page: page, include: include, from: from, to: to, content_type: content_type})
16
+ end
17
+
18
+ # Get a program information
19
+ # @param id [String] Program ID
20
+ # @param include [String] Comma-separated list of relationships to include. Available relationships: author.
21
+ def get(id:, include: nil)
22
+ request(:get, "#{PATH}/#{id}", params: {include: include})
23
+ end
24
+
25
+ # Get list of chapters
26
+ # @param id [String] Program ID
27
+ def chapters(id:)
28
+ request(:get, "#{PATH}/#{id}/chapters")
29
+ end
30
+
31
+ # Get a chapter
32
+ # @param id [String] Program ID
33
+ # @param chapter_id [String] Chapter ID
34
+ def chapter(id:, chapter_id:)
35
+ request(:get, "#{PATH}/#{id}/chapters/#{chapter_id}")
36
+ end
37
+ end
38
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module UscreenAPI
4
- VERSION = "0.1.2"
4
+ VERSION = "0.2.0"
5
5
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UscreenAPI
4
+ class Videos < Base
5
+ PATH = "videos"
6
+
7
+ # Get paginated list of videos
8
+ # @param page [Integer] Page number
9
+ # @param include [String] Comma-separated list of relationships to include. Available relationships: author.
10
+ # @param from [String] Starting date and time for the filter range, formatted in RFC 3339. Example: 2023-01-01T00:00:00Z
11
+ # @param to [String] Ending date and time for the filter range, formatted in RFC 3339. Example: 2023-01-01T00:00:00Z
12
+ def list(page: nil, include: nil, from: nil, to: nil)
13
+ request(:get, PATH, params: {page: page, include: include, from: from, to: to})
14
+ end
15
+
16
+ # Get video by ID
17
+ # @param id [String] Video ID
18
+ # @param include [String] Comma-separated list of relationships to include. Available relationships: author.
19
+ def get(id:, include: nil)
20
+ request(:get, "#{PATH}/#{id}", params: {include: include})
21
+ end
22
+ end
23
+ end
data/lib/uscreen_api.rb CHANGED
@@ -3,8 +3,16 @@
3
3
  require_relative "uscreen_api/version"
4
4
 
5
5
  module UscreenAPI
6
+ autoload :Analytics, "uscreen_api/analytics"
6
7
  autoload :Base, "uscreen_api/base"
7
8
  autoload :Client, "uscreen_api/client"
9
+ autoload :Contents, "uscreen_api/contents"
8
10
  autoload :Customers, "uscreen_api/customers"
11
+ autoload :EmailTopics, "uscreen_api/email_topics"
9
12
  autoload :Errors, "uscreen_api/errors"
13
+ autoload :Groups, "uscreen_api/groups"
14
+ autoload :Invoices, "uscreen_api/invoices"
15
+ autoload :Offers, "uscreen_api/offers"
16
+ autoload :Programs, "uscreen_api/programs"
17
+ autoload :Videos, "uscreen_api/videos"
10
18
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: uscreen_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrei Bondarev
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-03-28 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: faraday
@@ -61,11 +61,19 @@ files:
61
61
  - LICENSE.txt
62
62
  - README.md
63
63
  - lib/uscreen_api.rb
64
+ - lib/uscreen_api/analytics.rb
64
65
  - lib/uscreen_api/base.rb
65
66
  - lib/uscreen_api/client.rb
67
+ - lib/uscreen_api/contents.rb
66
68
  - lib/uscreen_api/customers.rb
69
+ - lib/uscreen_api/email_topics.rb
67
70
  - lib/uscreen_api/errors.rb
71
+ - lib/uscreen_api/groups.rb
72
+ - lib/uscreen_api/invoices.rb
73
+ - lib/uscreen_api/offers.rb
74
+ - lib/uscreen_api/programs.rb
68
75
  - lib/uscreen_api/version.rb
76
+ - lib/uscreen_api/videos.rb
69
77
  - sig/uscreen_api.rbs
70
78
  homepage: https://github.com/andreibondarev/uscreen_api
71
79
  licenses:
@@ -81,14 +89,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
81
89
  requirements:
82
90
  - - ">="
83
91
  - !ruby/object:Gem::Version
84
- version: 3.0.0
92
+ version: 3.2.0
85
93
  required_rubygems_version: !ruby/object:Gem::Requirement
86
94
  requirements:
87
95
  - - ">="
88
96
  - !ruby/object:Gem::Version
89
97
  version: '0'
90
98
  requirements: []
91
- rubygems_version: 3.6.2
99
+ rubygems_version: 3.6.9
92
100
  specification_version: 4
93
101
  summary: Uscreen.tv Publisher API client
94
102
  test_files: []