whatsapp_sdk 0.7.2 → 0.8.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/.rubocop.yml +4 -1
- data/CHANGELOG.md +8 -0
- data/Gemfile +0 -1
- data/Gemfile.lock +1 -4
- data/README.md +125 -1
- data/example.rb +55 -6
- data/lib/whatsapp_sdk/api/client.rb +3 -2
- data/lib/whatsapp_sdk/api/messages.rb +109 -24
- data/lib/whatsapp_sdk/resource/error.rb +39 -0
- data/lib/whatsapp_sdk/resource/interactive.rb +89 -0
- data/lib/whatsapp_sdk/resource/interactive_action.rb +133 -0
- data/lib/whatsapp_sdk/resource/interactive_action_reply_button.rb +88 -0
- data/lib/whatsapp_sdk/resource/interactive_action_section.rb +75 -0
- data/lib/whatsapp_sdk/resource/interactive_action_section_row.rb +94 -0
- data/lib/whatsapp_sdk/resource/interactive_body.rb +48 -0
- data/lib/whatsapp_sdk/resource/interactive_footer.rb +48 -0
- data/lib/whatsapp_sdk/resource/interactive_header.rb +120 -0
- data/lib/whatsapp_sdk/resource/parameter_object.rb +5 -18
- data/lib/whatsapp_sdk/version.rb +1 -1
- data/whatsapp_sdk.gemspec +0 -1
- metadata +11 -16
@@ -0,0 +1,89 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module WhatsappSdk
|
5
|
+
module Resource
|
6
|
+
class Interactive
|
7
|
+
extend T::Sig
|
8
|
+
|
9
|
+
class Type < T::Enum
|
10
|
+
extend T::Sig
|
11
|
+
|
12
|
+
enums do
|
13
|
+
ListMessage = new("list")
|
14
|
+
ReplyButton = new("button")
|
15
|
+
SingleProductMessage = new("product")
|
16
|
+
MultiProductMessage = new("product_list")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns the Interactive type of message you want to send.
|
21
|
+
#
|
22
|
+
# @returns type [Type]. Supported Options are list, button, product and product_list.
|
23
|
+
sig { returns(Type) }
|
24
|
+
attr_accessor :type
|
25
|
+
|
26
|
+
# Returns the interactive header if present. Required for type product_list.
|
27
|
+
#
|
28
|
+
# @returns type [InteractiveHeader] It can be nil.
|
29
|
+
sig { returns(T.nilable(InteractiveHeader)) }
|
30
|
+
attr_accessor :header
|
31
|
+
|
32
|
+
# Returns the interactive body.
|
33
|
+
#
|
34
|
+
# @returns type [InteractiveBody] Valid option is of type text only.
|
35
|
+
sig { returns(InteractiveBody) }
|
36
|
+
attr_accessor :body
|
37
|
+
|
38
|
+
# Returns the interactive footer if present.
|
39
|
+
#
|
40
|
+
# @returns type [InteractiveFooter] Valid option is of type text only. It can be nil.
|
41
|
+
sig { returns(T.nilable(InteractiveFooter)) }
|
42
|
+
attr_accessor :footer
|
43
|
+
|
44
|
+
# Returns the interactive action.
|
45
|
+
#
|
46
|
+
# @returns type [InteractiveBody] Valid condition is buttons of length of 1, 2 or 3 if type is button.
|
47
|
+
sig { returns(InteractiveAction) }
|
48
|
+
attr_accessor :action
|
49
|
+
|
50
|
+
sig do
|
51
|
+
params(
|
52
|
+
type: Type, body: InteractiveBody, action: InteractiveAction,
|
53
|
+
header: T.nilable(InteractiveHeader), footer: T.nilable(InteractiveFooter)
|
54
|
+
).void
|
55
|
+
end
|
56
|
+
def initialize(type:, body:, action:, header: nil, footer: nil)
|
57
|
+
@type = type
|
58
|
+
@body = body
|
59
|
+
@action = action
|
60
|
+
@header = header
|
61
|
+
@footer = footer
|
62
|
+
validate
|
63
|
+
end
|
64
|
+
|
65
|
+
sig { returns(T::Hash[T.untyped, T.untyped]) }
|
66
|
+
def to_json
|
67
|
+
json = { type: type.serialize }
|
68
|
+
json[:header] = header.to_json if header
|
69
|
+
json[:body] = body.to_json
|
70
|
+
json[:footer] = footer.to_json if footer
|
71
|
+
json[:action] = action.to_json
|
72
|
+
|
73
|
+
json
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
sig { void }
|
79
|
+
def validate
|
80
|
+
validate_action
|
81
|
+
end
|
82
|
+
|
83
|
+
sig { void }
|
84
|
+
def validate_action
|
85
|
+
action.validate
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module WhatsappSdk
|
5
|
+
module Resource
|
6
|
+
class InteractiveAction
|
7
|
+
extend T::Sig
|
8
|
+
|
9
|
+
class Type < T::Enum
|
10
|
+
extend T::Sig
|
11
|
+
|
12
|
+
enums do
|
13
|
+
ListMessage = new("list_message")
|
14
|
+
ReplyButton = new("reply_button")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns the type of interactive action you want to send.
|
19
|
+
#
|
20
|
+
# @returns type [Type]. Supported Options are list_message and reply_button.
|
21
|
+
sig { returns(Type) }
|
22
|
+
attr_accessor :type
|
23
|
+
|
24
|
+
# Returns the buttons of the Action. For reply_button type, it's required.
|
25
|
+
#
|
26
|
+
# @returns buttons [Array<InteractiveActionReplyButton>] .
|
27
|
+
sig { returns(T::Array[InteractiveActionReplyButton]) }
|
28
|
+
attr_accessor :buttons
|
29
|
+
|
30
|
+
# Returns the button of the Action. For list_message type, it's required.
|
31
|
+
#
|
32
|
+
# @returns button [String] .
|
33
|
+
sig { returns(String) }
|
34
|
+
attr_accessor :button
|
35
|
+
|
36
|
+
# Returns the sections of the Action. For list_message type, it's required.
|
37
|
+
#
|
38
|
+
# @returns sections [Array<InteractiveActionSection>] .
|
39
|
+
sig { returns(T::Array[InteractiveActionSection]) }
|
40
|
+
attr_accessor :sections
|
41
|
+
|
42
|
+
# TODO: attr_accessor :catalog_id
|
43
|
+
# TODO: attr_accessor :product_retailer_id
|
44
|
+
|
45
|
+
sig { params(reply_button: InteractiveActionReplyButton).void }
|
46
|
+
def add_reply_button(reply_button)
|
47
|
+
@buttons << reply_button
|
48
|
+
end
|
49
|
+
|
50
|
+
sig { params(section: InteractiveActionSection).void }
|
51
|
+
def add_section(section)
|
52
|
+
@sections << section
|
53
|
+
end
|
54
|
+
|
55
|
+
REPLY_BUTTONS_MINIMUM = 1
|
56
|
+
REPLY_BUTTONS_MAXIMUM = 3
|
57
|
+
LIST_BUTTON_TITLE_MAXIMUM = 20
|
58
|
+
LIST_SECTIONS_MINIMUM = 1
|
59
|
+
LIST_SECTIONS_MAXIMUM = 10
|
60
|
+
|
61
|
+
sig do
|
62
|
+
params(
|
63
|
+
type: Type, buttons: T::Array[InteractiveActionReplyButton],
|
64
|
+
button: String, sections: T::Array[InteractiveActionSection],
|
65
|
+
).void
|
66
|
+
end
|
67
|
+
def initialize(type:, buttons: [], button: "", sections: [])
|
68
|
+
@type = type
|
69
|
+
@buttons = buttons
|
70
|
+
@button = button
|
71
|
+
@sections = sections
|
72
|
+
end
|
73
|
+
|
74
|
+
sig { returns(T::Hash[T.untyped, T.untyped]) }
|
75
|
+
def to_json
|
76
|
+
json = {}
|
77
|
+
case type.serialize
|
78
|
+
when "list_message"
|
79
|
+
json = { button: button, sections: sections.map(&:to_json) }
|
80
|
+
when "reply_button"
|
81
|
+
json = { buttons: buttons.map(&:to_json) }
|
82
|
+
end
|
83
|
+
|
84
|
+
json
|
85
|
+
end
|
86
|
+
|
87
|
+
def validate
|
88
|
+
validate_fields
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def validate_fields
|
94
|
+
case type.serialize
|
95
|
+
when "list_message"
|
96
|
+
button_length = button.length
|
97
|
+
sections_count = sections.length
|
98
|
+
unless button_length > 0
|
99
|
+
raise WhatsappSdk::Resource::Error::InvalidInteractiveActionButton,
|
100
|
+
"Invalid button in action. Button label is required."
|
101
|
+
end
|
102
|
+
|
103
|
+
unless button_length <= LIST_BUTTON_TITLE_MAXIMUM
|
104
|
+
raise WhatsappSdk::Resource::Error::InvalidInteractiveActionButton,
|
105
|
+
"Invalid length #{button_length} for button. Maximum length: " \
|
106
|
+
"#{LIST_BUTTON_TITLE_MAXIMUM} characters."
|
107
|
+
end
|
108
|
+
|
109
|
+
unless (LIST_SECTIONS_MINIMUM..LIST_SECTIONS_MAXIMUM).cover?(sections_count)
|
110
|
+
raise WhatsappSdk::Resource::Error::InvalidInteractiveActionSection,
|
111
|
+
"Invalid length #{sections_count} for sections in action. It should be between " \
|
112
|
+
"#{LIST_SECTIONS_MINIMUM} and #{LIST_SECTIONS_MAXIMUM}."
|
113
|
+
end
|
114
|
+
|
115
|
+
sections.each { |section| section.validate }
|
116
|
+
when "reply_button"
|
117
|
+
buttons_count = buttons.length
|
118
|
+
unless (REPLY_BUTTONS_MINIMUM..REPLY_BUTTONS_MAXIMUM).cover?(buttons_count)
|
119
|
+
raise WhatsappSdk::Resource::Error::InvalidInteractiveActionReplyButton,
|
120
|
+
"Invalid length #{buttons_count} for buttons in action. It should be between " \
|
121
|
+
"#{REPLY_BUTTONS_MINIMUM} and #{REPLY_BUTTONS_MAXIMUM}."
|
122
|
+
end
|
123
|
+
|
124
|
+
button_ids = buttons.map(&:id)
|
125
|
+
return if button_ids.length.eql?(button_ids.uniq.length)
|
126
|
+
|
127
|
+
raise WhatsappSdk::Resource::Error::InvalidInteractiveActionReplyButton,
|
128
|
+
"Duplicate ids #{button_ids} for buttons in action. They should be unique."
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module WhatsappSdk
|
5
|
+
module Resource
|
6
|
+
class InteractiveActionReplyButton
|
7
|
+
extend T::Sig
|
8
|
+
|
9
|
+
class Type < T::Enum
|
10
|
+
extend T::Sig
|
11
|
+
|
12
|
+
enums do
|
13
|
+
Reply = new("reply")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns the ActionButton type of message you want to send.
|
18
|
+
#
|
19
|
+
# @returns type [String]. Supported Options are reply only.
|
20
|
+
sig { returns(Type) }
|
21
|
+
attr_accessor :type
|
22
|
+
|
23
|
+
# Returns the ActionButton title you want to send.
|
24
|
+
#
|
25
|
+
# @returns title [String]. The character limit is 20 characters.
|
26
|
+
sig { returns(String) }
|
27
|
+
attr_accessor :title
|
28
|
+
|
29
|
+
# Returns the ActionButton unique identifier you want to send.
|
30
|
+
# This ID is returned in the webhook when the button is clicked by the user.
|
31
|
+
#
|
32
|
+
# @returns id [String]. The character limit is 256 characters.
|
33
|
+
sig { returns(String) }
|
34
|
+
attr_accessor :id
|
35
|
+
|
36
|
+
ACTION_BUTTON_TITLE_MAXIMUM = 20
|
37
|
+
ACTION_BUTTON_ID_MAXIMUM = 256
|
38
|
+
|
39
|
+
sig { params(title: String, id: String).void }
|
40
|
+
def initialize(title:, id:)
|
41
|
+
@type = Type::Reply
|
42
|
+
@title = title
|
43
|
+
@id = id
|
44
|
+
validate
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_json
|
48
|
+
json = { type: type.serialize }
|
49
|
+
json[type.serialize.to_sym] = {
|
50
|
+
id: id,
|
51
|
+
title: title
|
52
|
+
}
|
53
|
+
|
54
|
+
json
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
sig { void }
|
60
|
+
def validate
|
61
|
+
validate_title
|
62
|
+
validate_id
|
63
|
+
end
|
64
|
+
|
65
|
+
sig { void }
|
66
|
+
def validate_title
|
67
|
+
title_length = title.length
|
68
|
+
return if title_length <= ACTION_BUTTON_TITLE_MAXIMUM
|
69
|
+
|
70
|
+
raise WhatsappSdk::Resource::Error::InvalidInteractiveActionReplyButton,
|
71
|
+
"Invalid length #{title_length} for title in button. " \
|
72
|
+
"Maximum length: #{ACTION_BUTTON_TITLE_MAXIMUM} characters."
|
73
|
+
end
|
74
|
+
|
75
|
+
sig { void }
|
76
|
+
def validate_id
|
77
|
+
id_unfrozen = id.dup
|
78
|
+
id_unfrozen.strip! # You cannot have leading or trailing spaces when setting the ID.
|
79
|
+
id = id_unfrozen.freeze
|
80
|
+
id_length = id.length
|
81
|
+
return if id_length <= ACTION_BUTTON_ID_MAXIMUM
|
82
|
+
|
83
|
+
raise WhatsappSdk::Resource::Error::InvalidInteractiveActionReplyButton,
|
84
|
+
"Invalid length #{id_length} for id in button. Maximum length: #{ACTION_BUTTON_ID_MAXIMUM} characters."
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module WhatsappSdk
|
5
|
+
module Resource
|
6
|
+
class InteractiveActionSection
|
7
|
+
extend T::Sig
|
8
|
+
|
9
|
+
# Returns the ActionSection title you want to send.
|
10
|
+
#
|
11
|
+
# @returns title [String]. The character limit is 24 characters.
|
12
|
+
sig { returns(String) }
|
13
|
+
attr_accessor :title
|
14
|
+
|
15
|
+
# Returns the ActionSection rows you want to send.
|
16
|
+
#
|
17
|
+
# @returns id [T::Array[InteractiveActionSectionRow]]. There must be at least one rows object.
|
18
|
+
sig { returns(T::Array[InteractiveActionSectionRow]) }
|
19
|
+
attr_accessor :rows
|
20
|
+
|
21
|
+
sig { params(row: InteractiveActionSectionRow).void }
|
22
|
+
def add_row(row)
|
23
|
+
@rows << row
|
24
|
+
end
|
25
|
+
|
26
|
+
ACTION_SECTION_TITLE_MAXIMUM = 24
|
27
|
+
ACTION_SECTION_ROWS_MAXIMUM = 10
|
28
|
+
|
29
|
+
sig { params(title: String, rows: T::Array[InteractiveActionSectionRow]).void }
|
30
|
+
def initialize(title:, rows: [])
|
31
|
+
@title = title
|
32
|
+
@rows = rows
|
33
|
+
validate(skip_rows: true)
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_json
|
37
|
+
json = {
|
38
|
+
title: title,
|
39
|
+
rows: rows.map(&:to_json),
|
40
|
+
}
|
41
|
+
|
42
|
+
json
|
43
|
+
end
|
44
|
+
|
45
|
+
sig { params(skip_rows: T.nilable(T::Boolean)).void }
|
46
|
+
def validate(skip_rows: false)
|
47
|
+
validate_title
|
48
|
+
validate_rows unless skip_rows
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
sig { void }
|
54
|
+
def validate_title
|
55
|
+
title_length = title.length
|
56
|
+
return if title_length <= ACTION_SECTION_TITLE_MAXIMUM
|
57
|
+
|
58
|
+
raise WhatsappSdk::Resource::Error::InvalidInteractiveActionSection,
|
59
|
+
"Invalid length #{title_length} for title in section. Maximum length: " \
|
60
|
+
"#{ACTION_SECTION_TITLE_MAXIMUM} characters."
|
61
|
+
end
|
62
|
+
|
63
|
+
sig { void }
|
64
|
+
def validate_rows
|
65
|
+
rows_length = rows.length
|
66
|
+
return if rows_length <= ACTION_SECTION_ROWS_MAXIMUM
|
67
|
+
|
68
|
+
raise WhatsappSdk::Resource::Error::InvalidInteractiveActionSection,
|
69
|
+
"Invalid number of rows #{rows_length} in section. Maximum count: " \
|
70
|
+
"#{ACTION_SECTION_ROWS_MAXIMUM}."
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module WhatsappSdk
|
5
|
+
module Resource
|
6
|
+
class InteractiveActionSectionRow
|
7
|
+
extend T::Sig
|
8
|
+
|
9
|
+
# Returns the ActionSection title you want to send.
|
10
|
+
#
|
11
|
+
# @returns title [String]. The character limit is 24 characters.
|
12
|
+
sig { returns(String) }
|
13
|
+
attr_accessor :title
|
14
|
+
|
15
|
+
# Returns the ActionSection description you want to send.
|
16
|
+
#
|
17
|
+
# @returns description [String]. The character limit is 72 characters if present.
|
18
|
+
sig { returns(String) }
|
19
|
+
attr_accessor :description
|
20
|
+
|
21
|
+
# Returns the ActionSection unique identifier you want to send.
|
22
|
+
# This ID is returned in the webhook when the section is selected by the user.
|
23
|
+
#
|
24
|
+
# @returns id [String]. The character limit is 256 characters.
|
25
|
+
sig { returns(String) }
|
26
|
+
attr_accessor :id
|
27
|
+
|
28
|
+
ACTION_SECTION_TITLE_MAXIMUM = 24
|
29
|
+
ACTION_SECTION_DESCRIPTION_MAXIMUM = 72
|
30
|
+
ACTION_SECTION_ID_MAXIMUM = 256
|
31
|
+
|
32
|
+
sig { params(title: String, id: String, description: T::nilable(String)).void }
|
33
|
+
def initialize(title:, id:, description: "")
|
34
|
+
@title = title
|
35
|
+
@id = id
|
36
|
+
@description = description
|
37
|
+
validate
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_json
|
41
|
+
json = {
|
42
|
+
id: id,
|
43
|
+
title: title
|
44
|
+
}
|
45
|
+
json[:description] = description if description.length > 0
|
46
|
+
|
47
|
+
json
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
sig { void }
|
53
|
+
def validate
|
54
|
+
validate_title
|
55
|
+
validate_id
|
56
|
+
validate_description
|
57
|
+
end
|
58
|
+
|
59
|
+
sig { void }
|
60
|
+
def validate_title
|
61
|
+
title_length = title.length
|
62
|
+
return if title_length <= ACTION_SECTION_TITLE_MAXIMUM
|
63
|
+
|
64
|
+
raise WhatsappSdk::Resource::Error::InvalidInteractiveActionSectionRow.new(
|
65
|
+
"Invalid length #{title_length} for title in section row. Maximum length: #{ACTION_SECTION_TITLE_MAXIMUM} characters.",
|
66
|
+
)
|
67
|
+
end
|
68
|
+
|
69
|
+
sig { void }
|
70
|
+
def validate_id
|
71
|
+
id_unfrozen = id.dup
|
72
|
+
id_unfrozen.strip! # You cannot have leading or trailing spaces when setting the ID.
|
73
|
+
id = id_unfrozen.freeze
|
74
|
+
id_length = id.length
|
75
|
+
return if id_length <= ACTION_SECTION_ID_MAXIMUM
|
76
|
+
|
77
|
+
raise WhatsappSdk::Resource::Error::InvalidInteractiveActionSectionRow.new(
|
78
|
+
"Invalid length #{id_length} for id in section row. Maximum length: #{ACTION_SECTION_ID_MAXIMUM} characters.",
|
79
|
+
)
|
80
|
+
end
|
81
|
+
|
82
|
+
sig { void }
|
83
|
+
def validate_description
|
84
|
+
description_length = description.length
|
85
|
+
return if description_length <= ACTION_SECTION_DESCRIPTION_MAXIMUM
|
86
|
+
|
87
|
+
raise WhatsappSdk::Resource::Error::InvalidInteractiveActionSectionRow.new(
|
88
|
+
"Invalid length #{description_length} for description in section row. Maximum length: #{ACTION_SECTION_DESCRIPTION_MAXIMUM} characters.",
|
89
|
+
)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module WhatsappSdk
|
5
|
+
module Resource
|
6
|
+
class InteractiveBody
|
7
|
+
extend T::Sig
|
8
|
+
|
9
|
+
# Returns Text string if the parameter object type is text.
|
10
|
+
# For the body interactive, the character limit is 1024 characters.
|
11
|
+
#
|
12
|
+
# @returns text [String]
|
13
|
+
sig { returns(String) }
|
14
|
+
attr_accessor :text
|
15
|
+
|
16
|
+
sig do
|
17
|
+
params(text: String).void
|
18
|
+
end
|
19
|
+
def initialize(text:)
|
20
|
+
@text = text
|
21
|
+
validate
|
22
|
+
end
|
23
|
+
|
24
|
+
sig { returns(T::Hash[T.untyped, T.untyped]) }
|
25
|
+
def to_json
|
26
|
+
{ text: text }
|
27
|
+
end
|
28
|
+
|
29
|
+
MAXIMUM_LENGTH = 1024
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
sig { void }
|
34
|
+
def validate
|
35
|
+
validate_text
|
36
|
+
end
|
37
|
+
|
38
|
+
sig { void }
|
39
|
+
def validate_text
|
40
|
+
text_length = text.length
|
41
|
+
return if text_length <= MAXIMUM_LENGTH
|
42
|
+
|
43
|
+
raise WhatsappSdk::Resource::Error::InvalidInteractiveBody,
|
44
|
+
"Invalid length #{text_length} for text in body. Maximum length: #{MAXIMUM_LENGTH} characters."
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module WhatsappSdk
|
5
|
+
module Resource
|
6
|
+
class InteractiveFooter
|
7
|
+
extend T::Sig
|
8
|
+
|
9
|
+
# Returns Text string if the parameter object type is text.
|
10
|
+
# For the body interactive, the character limit is 60 characters.
|
11
|
+
#
|
12
|
+
# @returns text [String]
|
13
|
+
sig { returns(String) }
|
14
|
+
attr_accessor :text
|
15
|
+
|
16
|
+
sig do
|
17
|
+
params(text: String).void
|
18
|
+
end
|
19
|
+
def initialize(text:)
|
20
|
+
@text = text
|
21
|
+
validate
|
22
|
+
end
|
23
|
+
|
24
|
+
sig { returns(T::Hash[T.untyped, T.untyped]) }
|
25
|
+
def to_json
|
26
|
+
{ text: text }
|
27
|
+
end
|
28
|
+
|
29
|
+
MAXIMUM_LENGTH = 60
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
sig { void }
|
34
|
+
def validate
|
35
|
+
validate_text
|
36
|
+
end
|
37
|
+
|
38
|
+
sig { void }
|
39
|
+
def validate_text
|
40
|
+
text_length = text.length
|
41
|
+
return if text_length <= MAXIMUM_LENGTH
|
42
|
+
|
43
|
+
raise WhatsappSdk::Resource::Error::InvalidInteractiveFooter,
|
44
|
+
"Invalid length #{text_length} for text in footer. Maximum length: #{MAXIMUM_LENGTH} characters."
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module WhatsappSdk
|
5
|
+
module Resource
|
6
|
+
class InteractiveHeader
|
7
|
+
extend T::Sig
|
8
|
+
|
9
|
+
# Returns the interactive header type.
|
10
|
+
#
|
11
|
+
# @returns type [String] Valid options are text, image, document, video.
|
12
|
+
sig { returns(Type) }
|
13
|
+
attr_accessor :type
|
14
|
+
|
15
|
+
class Type < T::Enum
|
16
|
+
extend T::Sig
|
17
|
+
|
18
|
+
enums do
|
19
|
+
Text = new("text")
|
20
|
+
Image = new("image")
|
21
|
+
Document = new("document")
|
22
|
+
Video = new("video")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Returns Text string if the interactive header type is text.
|
27
|
+
# For the header interactive, the character limit is 60 characters.
|
28
|
+
# For the body interactive, the character limit is 1024 characters.
|
29
|
+
#
|
30
|
+
# @returns text [String]
|
31
|
+
sig { returns(T.nilable(String)) }
|
32
|
+
attr_accessor :text
|
33
|
+
|
34
|
+
# Returns image if the interactive header type is image.
|
35
|
+
#
|
36
|
+
# @returns image [Media]
|
37
|
+
sig { returns(T.nilable(Media)) }
|
38
|
+
attr_accessor :image
|
39
|
+
|
40
|
+
# Returns document if the interactive header type is document.
|
41
|
+
#
|
42
|
+
# @returns document [Media]
|
43
|
+
sig { returns(T.nilable(Media)) }
|
44
|
+
attr_accessor :document
|
45
|
+
|
46
|
+
# Returns video if the interactive header type is video.
|
47
|
+
#
|
48
|
+
# @returns video [Media]
|
49
|
+
sig { returns(T.nilable(Media)) }
|
50
|
+
attr_accessor :video
|
51
|
+
|
52
|
+
sig do
|
53
|
+
params(
|
54
|
+
type: T.any(Type, String), text: T.nilable(String), image: T.nilable(Media),
|
55
|
+
document: T.nilable(Media), video: T.nilable(Media)
|
56
|
+
).void
|
57
|
+
end
|
58
|
+
def initialize(type:, text: nil, image: nil, document: nil, video: nil)
|
59
|
+
@type = T.let(deserialize_type(type), Type)
|
60
|
+
@text = text
|
61
|
+
@image = image
|
62
|
+
@document = document
|
63
|
+
@video = video
|
64
|
+
validate
|
65
|
+
end
|
66
|
+
|
67
|
+
sig { returns(T::Hash[T.untyped, T.untyped]) }
|
68
|
+
def to_json
|
69
|
+
json = { type: type.serialize }
|
70
|
+
json[type.serialize.to_sym] = case type.serialize
|
71
|
+
when "text"
|
72
|
+
text
|
73
|
+
when "image"
|
74
|
+
T.must(image).to_json
|
75
|
+
when "document"
|
76
|
+
T.must(document).to_json
|
77
|
+
when "video"
|
78
|
+
T.must(video).to_json
|
79
|
+
else
|
80
|
+
raise "Invalid type: #{type}"
|
81
|
+
end
|
82
|
+
|
83
|
+
json
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
sig { params(type: T.any(String, Type)).returns(Type) }
|
89
|
+
def deserialize_type(type)
|
90
|
+
return type if type.is_a?(Type)
|
91
|
+
|
92
|
+
Type.deserialize(type)
|
93
|
+
end
|
94
|
+
|
95
|
+
sig { void }
|
96
|
+
def validate
|
97
|
+
validate_attributes
|
98
|
+
end
|
99
|
+
|
100
|
+
sig { void }
|
101
|
+
def validate_attributes
|
102
|
+
[
|
103
|
+
[Type::Text, text],
|
104
|
+
[Type::Image, image],
|
105
|
+
[Type::Document, document],
|
106
|
+
[Type::Video, video]
|
107
|
+
].each do |type_b, value|
|
108
|
+
next unless type == type_b
|
109
|
+
|
110
|
+
next unless value.nil?
|
111
|
+
|
112
|
+
raise WhatsappSdk::Resource::Error::MissingValue.new(
|
113
|
+
type.serialize,
|
114
|
+
"#{type.serialize} is required when the type is #{type_b}"
|
115
|
+
)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|