sendly 3.37.1 → 3.38.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.
@@ -2,41 +2,74 @@
2
2
 
3
3
  module Sendly
4
4
  class Template
5
- attr_reader :id, :name, :body, :type, :locale, :variables, :is_default,
6
- :is_published, :created_at, :updated_at
5
+ attr_reader :id, :name, :text, :variables, :is_preset, :preset_slug,
6
+ :status, :version, :published_at, :created_at, :updated_at
7
7
 
8
+ # @deprecated Templates are not scoped by locale. The API returns no
9
+ # locale field, so this is always nil. There is no replacement.
10
+ attr_reader :locale
11
+
12
+ # @deprecated The API has no concept of a default template. It returns no
13
+ # such field, so this is always false. There is no replacement.
14
+ attr_reader :is_default
15
+
16
+ STATUSES = %w[draft published].freeze
17
+
18
+ # @deprecated Preset and custom are distinguished by {#is_preset} /
19
+ # {#preset?} now. For the values {#status} can hold, see {STATUSES}.
8
20
  TYPES = %w[preset custom].freeze
9
21
 
10
22
  def initialize(data)
11
23
  @id = data["id"]
12
24
  @name = data["name"]
13
- @body = data["body"]
14
- @type = data["type"] || "custom"
15
- @locale = data["locale"]
25
+ @text = data["text"]
16
26
  @variables = data["variables"] || []
27
+ @is_preset = data["is_preset"] || data["isPreset"] || false
28
+ @preset_slug = data["preset_slug"] || data["presetSlug"]
29
+ @status = data["status"]
30
+ @version = data["version"]
31
+ @published_at = parse_time(data["published_at"] || data["publishedAt"])
32
+ @created_at = parse_time(data["created_at"] || data["createdAt"])
33
+ @updated_at = parse_time(data["updated_at"] || data["updatedAt"])
34
+ @locale = data["locale"]
17
35
  @is_default = data["isDefault"] || data["is_default"] || false
18
- @is_published = data["isPublished"] || data["is_published"] || false
19
- @created_at = parse_time(data["createdAt"] || data["created_at"])
20
- @updated_at = parse_time(data["updatedAt"] || data["updated_at"])
36
+ end
37
+
38
+ alias body text
39
+
40
+ # @deprecated Use {#is_preset} or {#preset?}. Derived from {#is_preset}:
41
+ # "preset" for a preset template, "custom" for your own.
42
+ # @return [String]
43
+ def type
44
+ is_preset ? "preset" : "custom"
45
+ end
46
+
47
+ # @deprecated Use {#status} or {#published?}. Derived from {#status}.
48
+ # @return [Boolean]
49
+ def is_published
50
+ status == "published"
21
51
  end
22
52
 
23
53
  def preset?
24
- type == "preset"
54
+ is_preset
25
55
  end
26
56
 
27
57
  def custom?
28
- type == "custom"
58
+ !is_preset
29
59
  end
30
60
 
31
61
  def published?
32
- is_published
62
+ status == "published"
33
63
  end
34
64
 
35
65
  def to_h
36
66
  {
37
- id: id, name: name, body: body, type: type, locale: locale,
38
- variables: variables, is_default: is_default, is_published: is_published,
39
- created_at: created_at&.iso8601, updated_at: updated_at&.iso8601
67
+ id: id, name: name, text: text, variables: variables,
68
+ is_preset: is_preset, preset_slug: preset_slug, status: status,
69
+ version: version, published_at: published_at&.iso8601,
70
+ created_at: created_at&.iso8601, updated_at: updated_at&.iso8601,
71
+ body: body, type: type, locale: locale, is_default: is_default,
72
+ is_published: is_published
40
73
  }.compact
41
74
  end
42
75
 
@@ -55,56 +88,144 @@ module Sendly
55
88
  @client = client
56
89
  end
57
90
 
91
+ # List templates visible to the API key, presets included.
92
+ #
93
+ # @param limit [Integer, nil] Deprecated and unsupported. The list route
94
+ # returns every visible template in one response and does not paginate.
95
+ # Passing a value raises ArgumentError; slice the returned +:templates+
96
+ # array instead.
97
+ # @param type [String, nil] Deprecated and unsupported. The list route does
98
+ # not filter. Passing a value raises ArgumentError; select over the
99
+ # returned +:templates+ with {Template#preset?} / {Template#custom?}
100
+ # instead.
101
+ # @param locale [String, nil] Deprecated and unsupported. Templates are not
102
+ # scoped by locale. Passing a value raises ArgumentError; there is no
103
+ # replacement.
104
+ # @raise [ArgumentError] if +limit+, +type+ or +locale+ is given
105
+ # @return [Hash] +:templates+ (Array<Sendly::Template>) and +:pagination+,
106
+ # which is always nil because the route does not paginate
58
107
  def list(limit: nil, type: nil, locale: nil)
59
- params = {}
60
- params[:limit] = limit if limit
61
- params[:type] = type if type
62
- params[:locale] = locale if locale
63
-
64
- response = @client.get("/verify/templates", params)
65
- templates = (response["templates"] || []).map { |t| Template.new(t) }
66
- { templates: templates, pagination: response["pagination"] }
108
+ unless limit.nil?
109
+ raise ArgumentError,
110
+ "limit is not supported: the templates list route returns every " \
111
+ "visible template in one response and does not paginate. Slice " \
112
+ "the returned :templates array instead."
113
+ end
114
+
115
+ unless type.nil?
116
+ raise ArgumentError,
117
+ "type is not supported: the templates list route does not filter. " \
118
+ "Select over the returned :templates array with " \
119
+ "Sendly::Template#preset? or #custom? instead."
120
+ end
121
+
122
+ reject_locale!(locale)
123
+
124
+ response = @client.get("/templates")
125
+ {
126
+ templates: (response["templates"] || []).map { |t| Template.new(t) },
127
+ pagination: response["pagination"]
128
+ }
67
129
  end
68
130
 
69
131
  def get(id)
70
- response = @client.get("/verify/templates/#{id}")
132
+ response = @client.get("/templates/#{id}")
71
133
  Template.new(response)
72
134
  end
73
135
 
74
- def create(name:, body:, locale: nil, is_published: nil)
75
- request_body = { name: name, body: body }
76
- request_body[:locale] = locale if locale
77
- request_body[:isPublished] = is_published unless is_published.nil?
78
-
79
- response = @client.post("/verify/templates", request_body)
136
+ # Create a template. New templates start as drafts; call {#publish} to
137
+ # make one usable.
138
+ #
139
+ # @param name [String] Template name
140
+ # @param text [String] Template text, with +{{variable}}+ placeholders
141
+ # @param body [String, nil] Deprecated alias for +text+. Sent as +text+.
142
+ # Pass +text+.
143
+ # @param locale [String, nil] Deprecated and unsupported. Templates are not
144
+ # scoped by locale. Passing a value raises ArgumentError; there is no
145
+ # replacement.
146
+ # @param is_published [Boolean, nil] Deprecated. Templates are always
147
+ # created as drafts, so +false+ is accepted as a no-op and +true+ raises
148
+ # ArgumentError. Call {#publish} on the new template instead.
149
+ # @raise [ArgumentError] if +locale+ is given, if +is_published+ is true, or
150
+ # if neither +text+ nor +body+ is given
151
+ # @return [Sendly::Template]
152
+ def create(name:, text: nil, body: nil, locale: nil, is_published: nil)
153
+ reject_locale!(locale)
154
+
155
+ if is_published
156
+ raise ArgumentError,
157
+ "is_published: true is not supported on create: templates are " \
158
+ "always created as drafts. Publishing is a separate call - use " \
159
+ "publish(id) on the returned template instead."
160
+ end
161
+
162
+ content = text || body
163
+ raise ArgumentError, "text is required" if content.nil?
164
+
165
+ response = @client.post("/templates", { name: name, text: content })
80
166
  Template.new(response)
81
167
  end
82
168
 
83
- def update(id, name: nil, body: nil, locale: nil, is_published: nil)
169
+ # Update a draft template. Published templates cannot be edited; publish a
170
+ # new template instead.
171
+ #
172
+ # @param id [String] Template ID
173
+ # @param name [String, nil] New name
174
+ # @param text [String, nil] New template text
175
+ # @param body [String, nil] Deprecated alias for +text+. Sent as +text+.
176
+ # Pass +text+.
177
+ # @param locale [String, nil] Deprecated and unsupported. Templates are not
178
+ # scoped by locale. Passing a value raises ArgumentError; there is no
179
+ # replacement.
180
+ # @param is_published [Boolean, nil] Deprecated. An update never changes a
181
+ # template's status, and only drafts are editable, so +false+ is accepted
182
+ # as a no-op and +true+ raises ArgumentError. Call {#publish} instead.
183
+ # @raise [ArgumentError] if +locale+ is given or +is_published+ is true
184
+ # @return [Sendly::Template]
185
+ def update(id, name: nil, text: nil, body: nil, locale: nil, is_published: nil)
186
+ reject_locale!(locale)
187
+
188
+ if is_published
189
+ raise ArgumentError,
190
+ "is_published: true is not supported on update: an update never " \
191
+ "changes a template's status. Publishing is a separate call - " \
192
+ "use publish(id) instead."
193
+ end
194
+
195
+ content = text || body
196
+
84
197
  request_body = {}
85
198
  request_body[:name] = name if name
86
- request_body[:body] = body if body
87
- request_body[:locale] = locale if locale
88
- request_body[:isPublished] = is_published unless is_published.nil?
199
+ request_body[:text] = content if content
89
200
 
90
- response = @client.patch("/verify/templates/#{id}", request_body)
201
+ response = @client.patch("/templates/#{id}", request_body)
91
202
  Template.new(response)
92
203
  end
93
204
 
94
205
  def delete(id)
95
- @client.delete("/verify/templates/#{id}")
206
+ @client.delete("/templates/#{id}")
96
207
  end
97
208
 
98
209
  def publish(id)
99
- response = @client.post("/verify/templates/#{id}/publish")
210
+ response = @client.post("/templates/#{id}/publish")
100
211
  Template.new(response)
101
212
  end
102
213
 
214
+ # Unpublish a published template.
215
+ #
216
+ # @note Not available yet: the versioned API serves no unpublish route, so
217
+ # this call fails with a 404. To retire a published template today,
218
+ # {#create} and {#publish} a replacement, then {#delete} this one.
103
219
  def unpublish(id)
104
- response = @client.post("/verify/templates/#{id}/unpublish")
220
+ response = @client.post("/templates/#{id}/unpublish")
105
221
  Template.new(response)
106
222
  end
107
223
 
224
+ # Copy an existing template into a new draft.
225
+ #
226
+ # @note Not available yet: the versioned API serves no clone route, so
227
+ # this call fails with a 404. To copy a template today, read it with
228
+ # {#get} and pass its {Template#text} to {#create}.
108
229
  def clone(id, name: nil)
109
230
  body = {}
110
231
  body[:name] = name if name
@@ -118,5 +239,16 @@ module Sendly
118
239
  response = @client.post("/templates/generate", body)
119
240
  GeneratedTemplate.new(response)
120
241
  end
242
+
243
+ private
244
+
245
+ def reject_locale!(locale)
246
+ return if locale.nil?
247
+
248
+ raise ArgumentError,
249
+ "locale is not supported: templates are not scoped by locale and " \
250
+ "the API stores no locale field. There is no replacement - keep " \
251
+ "per-locale wording in separate templates."
252
+ end
121
253
  end
122
254
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sendly
4
- VERSION = "3.37.1"
4
+ VERSION = "3.38.0"
5
5
  end