activitysmith 0.1.6 → 0.1.7

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: 01ceddf3ae5045d286636cd3fa23783c922dc649b79e04ec96920994fbbf20e4
4
- data.tar.gz: 3beeee49f2549b2d76db40ad5ab3e68ebc47b19513090780ac1dbc8891599edb
3
+ metadata.gz: 6be18d3495ded4e85d34cb9dfa10b9108f9dbd5e35ace8bd6303867fb6b31172
4
+ data.tar.gz: 64b2d345bf824795d5b809d0ce5e9e40ee239d7f86878c20213704892f95db4e
5
5
  SHA512:
6
- metadata.gz: 82dac88237bf62fd4b7d9895d235a65d6b85cda0818a36808b6851779977e70b13e2f5e1066104f1590fda9b3d4f250198cb85da57c3a18fe3027ea5b0c9142f
7
- data.tar.gz: f0f9ed517c2fbe3e870061ce4ae7240b4efa93e66965f5c0779a79b9bbb0b5784fcb5e86eeba4d8d65a842a670f4aaa8d9895a0fbea5e0685789fa961c11139f
6
+ metadata.gz: 72f3a210715d8e9e660142c12ba0b5ae1d99bcd87fd49196c1aa8a6f4732b6aa83fd4408b11afc5816ef3e214804dfded8ba7dd23eb1ded669f805e1067df442
7
+ data.tar.gz: a022698cba1e043612fb3490fe3fc8805c20ef61dd8104137d74b3f8a0b36b9e378522ce76e5b4123a520a29ce2f1359f3fad6238758a701e7e672bca508ce8f
data/README.md CHANGED
@@ -214,6 +214,36 @@ response = activitysmith.notifications.send(
214
214
  )
215
215
  ```
216
216
 
217
+ ## Rich Push Notifications with Media
218
+
219
+ <p align="center">
220
+ <img src="https://cdn.activitysmith.com/features/rich-push-notification-with-image.png" alt="Rich push notification with image" width="680" />
221
+ </p>
222
+
223
+ ```ruby
224
+ response = activitysmith.notifications.send(
225
+ {
226
+ title: "Homepage ready",
227
+ message: "Your agent finished the redesign.",
228
+ media: "https://cdn.example.com/output/homepage-v2.png",
229
+ redirection: "https://github.com/acme/web/pull/482"
230
+ }
231
+ )
232
+ ```
233
+
234
+ Send images, videos, or audio with your push notifications, press and hold to preview media directly from the notification, then tap through to open the linked content.
235
+
236
+ <p align="center">
237
+ <img src="https://cdn.activitysmith.com/features/rich-push-notification-with-audio.png" alt="Rich push notification with audio" width="680" />
238
+ </p>
239
+
240
+ What will work:
241
+
242
+ - direct image URL: `.jpg`, `.png`, `.gif`, etc.
243
+ - direct audio file URL: `.mp3`, `.m4a`, etc.
244
+ - direct video file URL: `.mp4`, `.mov`, etc.
245
+ - URL that responds with a proper media `Content-Type`, even if the path has no extension
246
+
217
247
  ## Push Notification Redirection and Actions
218
248
 
219
249
  Push notification redirection and actions are optional and can be used to redirect the user to a specific URL when they tap the notification or to trigger a specific action when they long-press the notification.
@@ -20,7 +20,7 @@ module OpenapiClient
20
20
  @api_client = api_client
21
21
  end
22
22
  # Send a push notification
23
- # Sends a push notification to devices matched by API key scope and optional target channels. Supports optional redirection URL (tap) and up to 4 interactive actions (long-press on iOS).
23
+ # Sends a push notification to devices matched by API key scope and optional target channels. Supports optional redirection URL, optional media preview or playback when the notification is expanded, and up to 4 interactive actions. `media` cannot be combined with `actions`.
24
24
  # @param push_notification_request [PushNotificationRequest]
25
25
  # @param [Hash] opts the optional parameters
26
26
  # @return [PushNotificationResponse]
@@ -30,7 +30,7 @@ module OpenapiClient
30
30
  end
31
31
 
32
32
  # Send a push notification
33
- # Sends a push notification to devices matched by API key scope and optional target channels. Supports optional redirection URL (tap) and up to 4 interactive actions (long-press on iOS).
33
+ # Sends a push notification to devices matched by API key scope and optional target channels. Supports optional redirection URL, optional media preview or playback when the notification is expanded, and up to 4 interactive actions. &#x60;media&#x60; cannot be combined with &#x60;actions&#x60;.
34
34
  # @param push_notification_request [PushNotificationRequest]
35
35
  # @param [Hash] opts the optional parameters
36
36
  # @return [Array<(PushNotificationResponse, Integer, Hash)>] PushNotificationResponse data, response status code and response headers
@@ -21,10 +21,13 @@ module OpenapiClient
21
21
 
22
22
  attr_accessor :subtitle
23
23
 
24
- # Optional HTTPS URL opened when user taps the notification body.
24
+ # Optional HTTPS URL for an image, audio file, or video that users can preview or play when they expand the notification. If `redirection` is omitted, tapping the notification opens this URL. Cannot be combined with `actions`.
25
+ attr_accessor :media
26
+
27
+ # Optional HTTPS URL opened when user taps the notification body. Overrides the default tap target from `media` when both are provided.
25
28
  attr_accessor :redirection
26
29
 
27
- # Optional interactive actions shown on iOS long-press.
30
+ # Optional interactive actions shown when users expand the notification. Cannot be combined with `media`.
28
31
  attr_accessor :actions
29
32
 
30
33
  attr_accessor :payload
@@ -41,6 +44,7 @@ module OpenapiClient
41
44
  :'title' => :'title',
42
45
  :'message' => :'message',
43
46
  :'subtitle' => :'subtitle',
47
+ :'media' => :'media',
44
48
  :'redirection' => :'redirection',
45
49
  :'actions' => :'actions',
46
50
  :'payload' => :'payload',
@@ -61,6 +65,7 @@ module OpenapiClient
61
65
  :'title' => :'String',
62
66
  :'message' => :'String',
63
67
  :'subtitle' => :'String',
68
+ :'media' => :'String',
64
69
  :'redirection' => :'String',
65
70
  :'actions' => :'Array<PushNotificationAction>',
66
71
  :'payload' => :'Hash<String, Object>',
@@ -105,6 +110,10 @@ module OpenapiClient
105
110
  self.subtitle = attributes[:'subtitle']
106
111
  end
107
112
 
113
+ if attributes.key?(:'media')
114
+ self.media = attributes[:'media']
115
+ end
116
+
108
117
  if attributes.key?(:'redirection')
109
118
  self.redirection = attributes[:'redirection']
110
119
  end
@@ -143,6 +152,11 @@ module OpenapiClient
143
152
  invalid_properties.push('invalid value for "title", title cannot be nil.')
144
153
  end
145
154
 
155
+ pattern = Regexp.new(/^https:\/\//)
156
+ if !@media.nil? && @media !~ pattern
157
+ invalid_properties.push("invalid value for \"media\", must conform to the pattern #{pattern}.")
158
+ end
159
+
146
160
  pattern = Regexp.new(/^https:\/\//)
147
161
  if !@redirection.nil? && @redirection !~ pattern
148
162
  invalid_properties.push("invalid value for \"redirection\", must conform to the pattern #{pattern}.")
@@ -160,11 +174,27 @@ module OpenapiClient
160
174
  def valid?
161
175
  warn '[DEPRECATED] the `valid?` method is obsolete'
162
176
  return false if @title.nil?
177
+ return false if !@media.nil? && @media !~ Regexp.new(/^https:\/\//)
163
178
  return false if !@redirection.nil? && @redirection !~ Regexp.new(/^https:\/\//)
164
179
  return false if !@actions.nil? && @actions.length > 4
165
180
  true
166
181
  end
167
182
 
183
+ # Custom attribute writer method with validation
184
+ # @param [Object] media Value to be assigned
185
+ def media=(media)
186
+ if media.nil?
187
+ fail ArgumentError, 'media cannot be nil'
188
+ end
189
+
190
+ pattern = Regexp.new(/^https:\/\//)
191
+ if media !~ pattern
192
+ fail ArgumentError, "invalid value for \"media\", must conform to the pattern #{pattern}."
193
+ end
194
+
195
+ @media = media
196
+ end
197
+
168
198
  # Custom attribute writer method with validation
169
199
  # @param [Object] redirection Value to be assigned
170
200
  def redirection=(redirection)
@@ -202,6 +232,7 @@ module OpenapiClient
202
232
  title == o.title &&
203
233
  message == o.message &&
204
234
  subtitle == o.subtitle &&
235
+ media == o.media &&
205
236
  redirection == o.redirection &&
206
237
  actions == o.actions &&
207
238
  payload == o.payload &&
@@ -219,7 +250,7 @@ module OpenapiClient
219
250
  # Calculates hash code according to all attributes.
220
251
  # @return [Integer] Hash code
221
252
  def hash
222
- [title, message, subtitle, redirection, actions, payload, badge, sound, target].hash
253
+ [title, message, subtitle, media, redirection, actions, payload, badge, sound, target].hash
223
254
  end
224
255
 
225
256
  # Builds the object from hash
@@ -11,6 +11,7 @@ module ActivitySmith
11
11
 
12
12
  config = OpenapiClient::Configuration.new
13
13
  config.access_token = api_key
14
+ config.user_agent = VersionedUserAgent.value if config.respond_to?(:user_agent=)
14
15
 
15
16
  api_client = OpenapiClient::ApiClient.new(config)
16
17
  @notifications = Notifications.new(OpenapiClient::PushNotificationsApi.new(api_client))
@@ -7,12 +7,16 @@ module ActivitySmith
7
7
  end
8
8
 
9
9
  def send(request, opts = {})
10
- @api.send_push_notification(normalize_channels_target(request), opts)
10
+ normalized = normalize_channels_target(request)
11
+ assert_valid_media_actions!(normalized)
12
+ @api.send_push_notification(normalized, opts)
11
13
  end
12
14
 
13
15
  # Backward-compatible alias.
14
16
  def send_push_notification(push_notification_request, opts = {})
15
- @api.send_push_notification(normalize_channels_target(push_notification_request), opts)
17
+ normalized = normalize_channels_target(push_notification_request)
18
+ assert_valid_media_actions!(normalized)
19
+ @api.send_push_notification(normalized, opts)
16
20
  end
17
21
 
18
22
  def method_missing(name, *args, &block)
@@ -49,5 +53,29 @@ module ActivitySmith
49
53
  []
50
54
  end
51
55
  end
56
+
57
+ def assert_valid_media_actions!(request)
58
+ media = request_value(request, :media)
59
+ actions = request_value(request, :actions)
60
+ has_media = media.is_a?(String) ? !media.strip.empty? : !media.nil?
61
+ has_actions = actions.respond_to?(:empty?) ? !actions.empty? : !actions.nil?
62
+
63
+ return unless has_media && has_actions
64
+
65
+ raise ArgumentError, "ActivitySmith: media cannot be combined with actions"
66
+ end
67
+
68
+ def request_value(request, key)
69
+ if request.is_a?(Hash)
70
+ return request[key] if request.key?(key)
71
+ return request[key.to_s] if request.key?(key.to_s)
72
+
73
+ return nil
74
+ end
75
+
76
+ return request.public_send(key) if request.respond_to?(key)
77
+
78
+ nil
79
+ end
52
80
  end
53
81
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActivitySmith
4
- VERSION = "0.1.6"
4
+ VERSION = "0.1.7"
5
5
  end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActivitySmith
4
+ module VersionedUserAgent
5
+ def self.value
6
+ "activitysmith-ruby/#{ActivitySmith::VERSION}"
7
+ end
8
+ end
9
+ end
data/lib/activitysmith.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "activitysmith/version"
4
+ require_relative "activitysmith/versioned_user_agent"
4
5
  require_relative "activitysmith/notifications"
5
6
  require_relative "activitysmith/live_activities"
6
7
  require_relative "activitysmith/client"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activitysmith
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - ActivitySmith
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-03-10 00:00:00.000000000 Z
11
+ date: 2026-03-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -109,6 +109,7 @@ files:
109
109
  - lib/activitysmith/live_activities.rb
110
110
  - lib/activitysmith/notifications.rb
111
111
  - lib/activitysmith/version.rb
112
+ - lib/activitysmith/versioned_user_agent.rb
112
113
  homepage: https://activitysmith.com/docs/sdks/ruby
113
114
  licenses:
114
115
  - MIT