ruby-whatsapp 0.3.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 +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +54 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +15 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/LICENSE.txt +21 -0
- data/README.md +643 -0
- data/Rakefile +12 -0
- data/lib/ruby/whatsapp/client.rb +82 -0
- data/lib/ruby/whatsapp/configuration.rb +79 -0
- data/lib/ruby/whatsapp/instrumentation.rb +34 -0
- data/lib/ruby/whatsapp/media.rb +134 -0
- data/lib/ruby/whatsapp/message_templates/button/base.rb +26 -0
- data/lib/ruby/whatsapp/message_templates/button/copy_code.rb +59 -0
- data/lib/ruby/whatsapp/message_templates/button/otp/supported_app.rb +44 -0
- data/lib/ruby/whatsapp/message_templates/button/otp.rb +138 -0
- data/lib/ruby/whatsapp/message_templates/button/phone_number.rb +45 -0
- data/lib/ruby/whatsapp/message_templates/button/quick_reply.rb +38 -0
- data/lib/ruby/whatsapp/message_templates/button/url.rb +110 -0
- data/lib/ruby/whatsapp/message_templates/button.rb +56 -0
- data/lib/ruby/whatsapp/message_templates/categories.rb +47 -0
- data/lib/ruby/whatsapp/message_templates/component/base.rb +112 -0
- data/lib/ruby/whatsapp/message_templates/component/body.rb +139 -0
- data/lib/ruby/whatsapp/message_templates/component/buttons.rb +95 -0
- data/lib/ruby/whatsapp/message_templates/component/carousel/card.rb +100 -0
- data/lib/ruby/whatsapp/message_templates/component/carousel.rb +71 -0
- data/lib/ruby/whatsapp/message_templates/component/footer.rb +99 -0
- data/lib/ruby/whatsapp/message_templates/component/header.rb +188 -0
- data/lib/ruby/whatsapp/message_templates/component/limited_time_offer.rb +57 -0
- data/lib/ruby/whatsapp/message_templates/component.rb +62 -0
- data/lib/ruby/whatsapp/message_templates/component_set.rb +221 -0
- data/lib/ruby/whatsapp/message_templates/example.rb +148 -0
- data/lib/ruby/whatsapp/message_templates/library_template/body_inputs.rb +81 -0
- data/lib/ruby/whatsapp/message_templates/library_template/button_inputs.rb +146 -0
- data/lib/ruby/whatsapp/message_templates/library_template.rb +114 -0
- data/lib/ruby/whatsapp/message_templates/parameter_formats.rb +49 -0
- data/lib/ruby/whatsapp/message_templates/placeholders.rb +86 -0
- data/lib/ruby/whatsapp/message_templates/response/collection.rb +74 -0
- data/lib/ruby/whatsapp/message_templates/response/created.rb +65 -0
- data/lib/ruby/whatsapp/message_templates/response/node.rb +152 -0
- data/lib/ruby/whatsapp/message_templates/response/paging.rb +39 -0
- data/lib/ruby/whatsapp/message_templates/response/quality_score.rb +49 -0
- data/lib/ruby/whatsapp/message_templates/response/summary.rb +68 -0
- data/lib/ruby/whatsapp/message_templates/response.rb +22 -0
- data/lib/ruby/whatsapp/message_templates/statuses.rb +66 -0
- data/lib/ruby/whatsapp/message_templates/template.rb +180 -0
- data/lib/ruby/whatsapp/message_templates/value_object.rb +62 -0
- data/lib/ruby/whatsapp/message_templates.rb +283 -0
- data/lib/ruby/whatsapp/messages/address.rb +103 -0
- data/lib/ruby/whatsapp/messages/audio.rb +64 -0
- data/lib/ruby/whatsapp/messages/base.rb +46 -0
- data/lib/ruby/whatsapp/messages/contacts/address.rb +84 -0
- data/lib/ruby/whatsapp/messages/contacts/contact.rb +78 -0
- data/lib/ruby/whatsapp/messages/contacts/email.rb +49 -0
- data/lib/ruby/whatsapp/messages/contacts/name.rb +68 -0
- data/lib/ruby/whatsapp/messages/contacts/org.rb +41 -0
- data/lib/ruby/whatsapp/messages/contacts/phone.rb +59 -0
- data/lib/ruby/whatsapp/messages/contacts/url.rb +51 -0
- data/lib/ruby/whatsapp/messages/contacts.rb +37 -0
- data/lib/ruby/whatsapp/messages/document.rb +79 -0
- data/lib/ruby/whatsapp/messages/image.rb +72 -0
- data/lib/ruby/whatsapp/messages/interactive/base.rb +15 -0
- data/lib/ruby/whatsapp/messages/interactive/body.rb +39 -0
- data/lib/ruby/whatsapp/messages/interactive/footer.rb +40 -0
- data/lib/ruby/whatsapp/messages/interactive/header.rb +102 -0
- data/lib/ruby/whatsapp/messages/interactive/list_buttons/section/row.rb +66 -0
- data/lib/ruby/whatsapp/messages/interactive/list_buttons/section.rb +64 -0
- data/lib/ruby/whatsapp/messages/interactive/list_buttons.rb +63 -0
- data/lib/ruby/whatsapp/messages/interactive/media_carousel/card/button/quick_reply.rb +50 -0
- data/lib/ruby/whatsapp/messages/interactive/media_carousel/card/button.rb +47 -0
- data/lib/ruby/whatsapp/messages/interactive/media_carousel/card.rb +78 -0
- data/lib/ruby/whatsapp/messages/interactive/media_carousel.rb +50 -0
- data/lib/ruby/whatsapp/messages/interactive/product_carousel/card.rb +55 -0
- data/lib/ruby/whatsapp/messages/interactive/product_carousel.rb +50 -0
- data/lib/ruby/whatsapp/messages/interactive/reply_buttons/button.rb +59 -0
- data/lib/ruby/whatsapp/messages/interactive/reply_buttons.rb +47 -0
- data/lib/ruby/whatsapp/messages/interactive/url_button.rb +68 -0
- data/lib/ruby/whatsapp/messages/interactive.rb +112 -0
- data/lib/ruby/whatsapp/messages/location.rb +67 -0
- data/lib/ruby/whatsapp/messages/location_request.rb +41 -0
- data/lib/ruby/whatsapp/messages/mark_message_as_read.rb +42 -0
- data/lib/ruby/whatsapp/messages/reaction.rb +61 -0
- data/lib/ruby/whatsapp/messages/response/contacts.rb +36 -0
- data/lib/ruby/whatsapp/messages/response/messages.rb +27 -0
- data/lib/ruby/whatsapp/messages/response.rb +49 -0
- data/lib/ruby/whatsapp/messages/sticker.rb +62 -0
- data/lib/ruby/whatsapp/messages/template/component.rb +67 -0
- data/lib/ruby/whatsapp/messages/template/language.rb +55 -0
- data/lib/ruby/whatsapp/messages/template/parameter.rb +113 -0
- data/lib/ruby/whatsapp/messages/template.rb +62 -0
- data/lib/ruby/whatsapp/messages/text.rb +43 -0
- data/lib/ruby/whatsapp/messages/video.rb +68 -0
- data/lib/ruby/whatsapp/messages.rb +116 -0
- data/lib/ruby/whatsapp/railtie.rb +14 -0
- data/lib/ruby/whatsapp/request_error.rb +5 -0
- data/lib/ruby/whatsapp/response_handling.rb +44 -0
- data/lib/ruby/whatsapp/utils/language_codes.rb +96 -0
- data/lib/ruby/whatsapp/version.rb +5 -0
- data/lib/ruby/whatsapp/webhook/account_alerts.rb +58 -0
- data/lib/ruby/whatsapp/webhook/account_review_update.rb +27 -0
- data/lib/ruby/whatsapp/webhook/account_update/ban_info.rb +33 -0
- data/lib/ruby/whatsapp/webhook/account_update.rb +46 -0
- data/lib/ruby/whatsapp/webhook/automatic_events.rb +43 -0
- data/lib/ruby/whatsapp/webhook/business_capability_update.rb +36 -0
- data/lib/ruby/whatsapp/webhook/change.rb +61 -0
- data/lib/ruby/whatsapp/webhook/contact.rb +36 -0
- data/lib/ruby/whatsapp/webhook/entry.rb +35 -0
- data/lib/ruby/whatsapp/webhook/error.rb +47 -0
- data/lib/ruby/whatsapp/webhook/history.rb +54 -0
- data/lib/ruby/whatsapp/webhook/installer.rb +61 -0
- data/lib/ruby/whatsapp/webhook/message/audio.rb +28 -0
- data/lib/ruby/whatsapp/webhook/message/base.rb +61 -0
- data/lib/ruby/whatsapp/webhook/message/button.rb +33 -0
- data/lib/ruby/whatsapp/webhook/message/contacts/address.rb +68 -0
- data/lib/ruby/whatsapp/webhook/message/contacts/contact.rb +68 -0
- data/lib/ruby/whatsapp/webhook/message/contacts/email.rb +35 -0
- data/lib/ruby/whatsapp/webhook/message/contacts/name.rb +62 -0
- data/lib/ruby/whatsapp/webhook/message/contacts/org.rb +40 -0
- data/lib/ruby/whatsapp/webhook/message/contacts/phone.rb +40 -0
- data/lib/ruby/whatsapp/webhook/message/contacts/url.rb +35 -0
- data/lib/ruby/whatsapp/webhook/message/contacts.rb +31 -0
- data/lib/ruby/whatsapp/webhook/message/context.rb +49 -0
- data/lib/ruby/whatsapp/webhook/message/document.rb +32 -0
- data/lib/ruby/whatsapp/webhook/message/image.rb +18 -0
- data/lib/ruby/whatsapp/webhook/message/interactive.rb +53 -0
- data/lib/ruby/whatsapp/webhook/message/location.rb +49 -0
- data/lib/ruby/whatsapp/webhook/message/media.rb +54 -0
- data/lib/ruby/whatsapp/webhook/message/order/product_item.rb +50 -0
- data/lib/ruby/whatsapp/webhook/message/order.rb +43 -0
- data/lib/ruby/whatsapp/webhook/message/reaction.rb +37 -0
- data/lib/ruby/whatsapp/webhook/message/referral.rb +80 -0
- data/lib/ruby/whatsapp/webhook/message/sticker.rb +32 -0
- data/lib/ruby/whatsapp/webhook/message/system.rb +49 -0
- data/lib/ruby/whatsapp/webhook/message/text.rb +28 -0
- data/lib/ruby/whatsapp/webhook/message/unknown.rb +39 -0
- data/lib/ruby/whatsapp/webhook/message/video.rb +18 -0
- data/lib/ruby/whatsapp/webhook/message.rb +39 -0
- data/lib/ruby/whatsapp/webhook/message_template_components_update.rb +53 -0
- data/lib/ruby/whatsapp/webhook/message_template_quality_update.rb +59 -0
- data/lib/ruby/whatsapp/webhook/message_template_status_update.rb +54 -0
- data/lib/ruby/whatsapp/webhook/messages.rb +55 -0
- data/lib/ruby/whatsapp/webhook/metadata.rb +35 -0
- data/lib/ruby/whatsapp/webhook/notification.rb +36 -0
- data/lib/ruby/whatsapp/webhook/partner_solutions.rb +36 -0
- data/lib/ruby/whatsapp/webhook/payment_configuration_update.rb +51 -0
- data/lib/ruby/whatsapp/webhook/phone_number_name_update.rb +51 -0
- data/lib/ruby/whatsapp/webhook/phone_number_quality_update.rb +45 -0
- data/lib/ruby/whatsapp/webhook/security.rb +41 -0
- data/lib/ruby/whatsapp/webhook/signature.rb +28 -0
- data/lib/ruby/whatsapp/webhook/smb_app_state_sync/state_sync.rb +38 -0
- data/lib/ruby/whatsapp/webhook/smb_app_state_sync.rb +33 -0
- data/lib/ruby/whatsapp/webhook/smb_message_echoes.rb +48 -0
- data/lib/ruby/whatsapp/webhook/status/conversation.rb +42 -0
- data/lib/ruby/whatsapp/webhook/status/pricing.rb +38 -0
- data/lib/ruby/whatsapp/webhook/status.rb +65 -0
- data/lib/ruby/whatsapp/webhook/template_category_update.rb +64 -0
- data/lib/ruby/whatsapp/webhook/templates/webhooks_controller.rb.tt +31 -0
- data/lib/ruby/whatsapp/webhook/unknown_field.rb +37 -0
- data/lib/ruby/whatsapp/webhook/user_preferences.rb +47 -0
- data/lib/ruby/whatsapp/webhook/verification.rb +27 -0
- data/lib/ruby/whatsapp/webhook.rb +8 -0
- data/lib/ruby/whatsapp.rb +49 -0
- data/lib/tasks/whatsapp.rake +10 -0
- data/sig/ruby/whatsapp.rbs +6 -0
- metadata +267 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Whatsapp
|
|
4
|
+
module Webhook
|
|
5
|
+
class Message
|
|
6
|
+
# Shared shape for the media-backed message types (image, video, audio,
|
|
7
|
+
# document, sticker) — a media asset id you can resolve via {Whatsapp::Media},
|
|
8
|
+
# plus its mime type and content hash.
|
|
9
|
+
class Media < Base
|
|
10
|
+
# @!attribute [rw] media_id
|
|
11
|
+
# @return [String, nil] The media asset id (resolve via {Whatsapp::Media#url}).
|
|
12
|
+
attr_accessor :media_id
|
|
13
|
+
|
|
14
|
+
# @!attribute [rw] mime_type
|
|
15
|
+
# @return [String, nil]
|
|
16
|
+
attr_accessor :mime_type
|
|
17
|
+
|
|
18
|
+
# @!attribute [rw] sha256
|
|
19
|
+
# @return [String, nil]
|
|
20
|
+
attr_accessor :sha256
|
|
21
|
+
|
|
22
|
+
# @!attribute [rw] caption
|
|
23
|
+
# @return [String, nil]
|
|
24
|
+
attr_accessor :caption
|
|
25
|
+
|
|
26
|
+
def initialize(media_id:, mime_type:, sha256:, caption: nil, **base_attributes)
|
|
27
|
+
super(**base_attributes)
|
|
28
|
+
|
|
29
|
+
@media_id = media_id
|
|
30
|
+
@mime_type = mime_type
|
|
31
|
+
@sha256 = sha256
|
|
32
|
+
@caption = caption
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
class << self
|
|
36
|
+
# Extracts the media-specific fields nested under the given key
|
|
37
|
+
# (e.g. `"image"`, `"video"`), for subclasses to merge with their own
|
|
38
|
+
# extra attributes before calling `new`.
|
|
39
|
+
# @param data [Hash] The raw message hash.
|
|
40
|
+
# @param key [String] The type-specific nested key (e.g. `"image"`).
|
|
41
|
+
# @return [Hash]
|
|
42
|
+
def media_attributes(data, key)
|
|
43
|
+
{
|
|
44
|
+
media_id: data.dig(key, "id"),
|
|
45
|
+
mime_type: data.dig(key, "mime_type"),
|
|
46
|
+
sha256: data.dig(key, "sha256"),
|
|
47
|
+
caption: data.dig(key, "caption"),
|
|
48
|
+
}
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Whatsapp
|
|
4
|
+
module Webhook
|
|
5
|
+
class Message
|
|
6
|
+
class Order < Base
|
|
7
|
+
# A single line item within an inbound order message.
|
|
8
|
+
class ProductItem
|
|
9
|
+
# @!attribute [rw] product_retailer_id
|
|
10
|
+
# @return [String, nil] The catalog SKU.
|
|
11
|
+
attr_accessor :product_retailer_id
|
|
12
|
+
|
|
13
|
+
# @!attribute [rw] quantity
|
|
14
|
+
# @return [Integer, nil]
|
|
15
|
+
attr_accessor :quantity
|
|
16
|
+
|
|
17
|
+
# @!attribute [rw] item_price
|
|
18
|
+
# @return [Float, nil]
|
|
19
|
+
attr_accessor :item_price
|
|
20
|
+
|
|
21
|
+
# @!attribute [rw] currency
|
|
22
|
+
# @return [String, nil]
|
|
23
|
+
attr_accessor :currency
|
|
24
|
+
|
|
25
|
+
def initialize(product_retailer_id:, quantity:, item_price:, currency:)
|
|
26
|
+
@product_retailer_id = product_retailer_id
|
|
27
|
+
@quantity = quantity
|
|
28
|
+
@item_price = item_price
|
|
29
|
+
@currency = currency
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class << self
|
|
33
|
+
# @param data [Hash] A raw `product_items[]` entry.
|
|
34
|
+
# @return [ProductItem]
|
|
35
|
+
def deserialize(data)
|
|
36
|
+
data ||= {}
|
|
37
|
+
|
|
38
|
+
new(
|
|
39
|
+
product_retailer_id: data["product_retailer_id"],
|
|
40
|
+
quantity: data["quantity"],
|
|
41
|
+
item_price: data["item_price"],
|
|
42
|
+
currency: data["currency"]
|
|
43
|
+
)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Whatsapp
|
|
4
|
+
module Webhook
|
|
5
|
+
class Message
|
|
6
|
+
# An inbound order placed against a Meta catalog.
|
|
7
|
+
class Order < Base
|
|
8
|
+
# @!attribute [rw] catalog_id
|
|
9
|
+
# @return [String, nil]
|
|
10
|
+
attr_accessor :catalog_id
|
|
11
|
+
|
|
12
|
+
# @!attribute [rw] text
|
|
13
|
+
# @return [String, nil] Optional note the customer attached to the order.
|
|
14
|
+
attr_accessor :text
|
|
15
|
+
|
|
16
|
+
# @!attribute [rw] product_items
|
|
17
|
+
# @return [Array<ProductItem>]
|
|
18
|
+
attr_accessor :product_items
|
|
19
|
+
|
|
20
|
+
def initialize(catalog_id:, product_items:, text: nil, **base_attributes)
|
|
21
|
+
super(**base_attributes)
|
|
22
|
+
|
|
23
|
+
@catalog_id = catalog_id
|
|
24
|
+
@text = text
|
|
25
|
+
@product_items = product_items
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class << self
|
|
29
|
+
# @param data [Hash] The raw message hash.
|
|
30
|
+
# @return [Order]
|
|
31
|
+
def deserialize(data)
|
|
32
|
+
new(
|
|
33
|
+
catalog_id: data.dig("order", "catalog_id"),
|
|
34
|
+
text: data.dig("order", "text"),
|
|
35
|
+
product_items: Array(data.dig("order", "product_items")).map { |item| ProductItem.deserialize(item) },
|
|
36
|
+
**common_attributes(data)
|
|
37
|
+
)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Whatsapp
|
|
4
|
+
module Webhook
|
|
5
|
+
class Message
|
|
6
|
+
# An inbound emoji reaction to a previous message.
|
|
7
|
+
class Reaction < Base
|
|
8
|
+
# @!attribute [rw] message_id
|
|
9
|
+
# @return [String, nil] The wamid of the message being reacted to.
|
|
10
|
+
attr_accessor :message_id
|
|
11
|
+
|
|
12
|
+
# @!attribute [rw] emoji
|
|
13
|
+
# @return [String, nil] Empty when the user removed a previous reaction.
|
|
14
|
+
attr_accessor :emoji
|
|
15
|
+
|
|
16
|
+
def initialize(message_id:, emoji:, **base_attributes)
|
|
17
|
+
super(**base_attributes)
|
|
18
|
+
|
|
19
|
+
@message_id = message_id
|
|
20
|
+
@emoji = emoji
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
class << self
|
|
24
|
+
# @param data [Hash] The raw message hash.
|
|
25
|
+
# @return [Reaction]
|
|
26
|
+
def deserialize(data)
|
|
27
|
+
new(
|
|
28
|
+
message_id: data.dig("reaction", "message_id"),
|
|
29
|
+
emoji: data.dig("reaction", "emoji"),
|
|
30
|
+
**common_attributes(data)
|
|
31
|
+
)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Whatsapp
|
|
4
|
+
module Webhook
|
|
5
|
+
class Message
|
|
6
|
+
# Present when an inbound message originated from a Click-to-WhatsApp ad or a
|
|
7
|
+
# post/story with an embedded WhatsApp link.
|
|
8
|
+
class Referral
|
|
9
|
+
# @!attribute [rw] source_url
|
|
10
|
+
# @return [String, nil]
|
|
11
|
+
attr_accessor :source_url
|
|
12
|
+
|
|
13
|
+
# @!attribute [rw] source_type
|
|
14
|
+
# @return [String, nil]
|
|
15
|
+
attr_accessor :source_type
|
|
16
|
+
|
|
17
|
+
# @!attribute [rw] source_id
|
|
18
|
+
# @return [String, nil]
|
|
19
|
+
attr_accessor :source_id
|
|
20
|
+
|
|
21
|
+
# @!attribute [rw] headline
|
|
22
|
+
# @return [String, nil]
|
|
23
|
+
attr_accessor :headline
|
|
24
|
+
|
|
25
|
+
# @!attribute [rw] body
|
|
26
|
+
# @return [String, nil]
|
|
27
|
+
attr_accessor :body
|
|
28
|
+
|
|
29
|
+
# @!attribute [rw] media_type
|
|
30
|
+
# @return [String, nil]
|
|
31
|
+
attr_accessor :media_type
|
|
32
|
+
|
|
33
|
+
# @!attribute [rw] image_url
|
|
34
|
+
# @return [String, nil]
|
|
35
|
+
attr_accessor :image_url
|
|
36
|
+
|
|
37
|
+
# @!attribute [rw] video_url
|
|
38
|
+
# @return [String, nil]
|
|
39
|
+
attr_accessor :video_url
|
|
40
|
+
|
|
41
|
+
# @!attribute [rw] thumbnail_url
|
|
42
|
+
# @return [String, nil]
|
|
43
|
+
attr_accessor :thumbnail_url
|
|
44
|
+
|
|
45
|
+
def initialize(source_url:, source_type:, source_id:, headline:, body:, media_type:, image_url: nil,
|
|
46
|
+
video_url: nil, thumbnail_url: nil)
|
|
47
|
+
@source_url = source_url
|
|
48
|
+
@source_type = source_type
|
|
49
|
+
@source_id = source_id
|
|
50
|
+
@headline = headline
|
|
51
|
+
@body = body
|
|
52
|
+
@media_type = media_type
|
|
53
|
+
@image_url = image_url
|
|
54
|
+
@video_url = video_url
|
|
55
|
+
@thumbnail_url = thumbnail_url
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
class << self
|
|
59
|
+
# @param data [Hash, nil] The raw `referral` hash.
|
|
60
|
+
# @return [Referral, nil]
|
|
61
|
+
def deserialize(data)
|
|
62
|
+
return if data.nil?
|
|
63
|
+
|
|
64
|
+
new(
|
|
65
|
+
source_url: data["source_url"],
|
|
66
|
+
source_type: data["source_type"],
|
|
67
|
+
source_id: data["source_id"],
|
|
68
|
+
headline: data["headline"],
|
|
69
|
+
body: data["body"],
|
|
70
|
+
media_type: data["media_type"],
|
|
71
|
+
image_url: data["image_url"],
|
|
72
|
+
video_url: data["video_url"],
|
|
73
|
+
thumbnail_url: data["thumbnail_url"]
|
|
74
|
+
)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Whatsapp
|
|
4
|
+
module Webhook
|
|
5
|
+
class Message
|
|
6
|
+
# An inbound sticker message.
|
|
7
|
+
class Sticker < Media
|
|
8
|
+
# @!attribute [rw] animated
|
|
9
|
+
# @return [Boolean, nil]
|
|
10
|
+
attr_accessor :animated
|
|
11
|
+
|
|
12
|
+
def initialize(animated: nil, **media_and_base_attributes)
|
|
13
|
+
super(**media_and_base_attributes)
|
|
14
|
+
|
|
15
|
+
@animated = animated
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class << self
|
|
19
|
+
# @param data [Hash] The raw message hash.
|
|
20
|
+
# @return [Sticker]
|
|
21
|
+
def deserialize(data)
|
|
22
|
+
new(
|
|
23
|
+
animated: data.dig("sticker", "animated"),
|
|
24
|
+
**media_attributes(data, "sticker"),
|
|
25
|
+
**common_attributes(data)
|
|
26
|
+
)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Whatsapp
|
|
4
|
+
module Webhook
|
|
5
|
+
class Message
|
|
6
|
+
# A system notice, e.g. that the customer changed their phone number.
|
|
7
|
+
class System < Base
|
|
8
|
+
# @!attribute [rw] body
|
|
9
|
+
# @return [String, nil] Human-readable description of the change.
|
|
10
|
+
attr_accessor :body
|
|
11
|
+
|
|
12
|
+
# @!attribute [rw] identity
|
|
13
|
+
# @return [String, nil]
|
|
14
|
+
attr_accessor :identity
|
|
15
|
+
|
|
16
|
+
# @!attribute [rw] wa_id
|
|
17
|
+
# @return [String, nil] The customer's (possibly new) WhatsApp ID.
|
|
18
|
+
attr_accessor :wa_id
|
|
19
|
+
|
|
20
|
+
# @!attribute [rw] change_type
|
|
21
|
+
# @return [String, nil] e.g. `"customer_changed_number"`, `"customer_identity_changed"`.
|
|
22
|
+
attr_accessor :change_type
|
|
23
|
+
|
|
24
|
+
def initialize(body:, identity:, wa_id:, change_type:, **base_attributes)
|
|
25
|
+
super(**base_attributes)
|
|
26
|
+
|
|
27
|
+
@body = body
|
|
28
|
+
@identity = identity
|
|
29
|
+
@wa_id = wa_id
|
|
30
|
+
@change_type = change_type
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
class << self
|
|
34
|
+
# @param data [Hash] The raw message hash.
|
|
35
|
+
# @return [System]
|
|
36
|
+
def deserialize(data)
|
|
37
|
+
new(
|
|
38
|
+
body: data.dig("system", "body"),
|
|
39
|
+
identity: data.dig("system", "identity"),
|
|
40
|
+
wa_id: data.dig("system", "wa_id"),
|
|
41
|
+
change_type: data.dig("system", "type"),
|
|
42
|
+
**common_attributes(data)
|
|
43
|
+
)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Whatsapp
|
|
4
|
+
module Webhook
|
|
5
|
+
class Message
|
|
6
|
+
# An inbound plain-text message.
|
|
7
|
+
class Text < Base
|
|
8
|
+
# @!attribute [rw] body
|
|
9
|
+
# @return [String, nil]
|
|
10
|
+
attr_accessor :body
|
|
11
|
+
|
|
12
|
+
def initialize(body:, **base_attributes)
|
|
13
|
+
super(**base_attributes)
|
|
14
|
+
|
|
15
|
+
@body = body
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class << self
|
|
19
|
+
# @param data [Hash] The raw message hash.
|
|
20
|
+
# @return [Text]
|
|
21
|
+
def deserialize(data)
|
|
22
|
+
new(body: data.dig("text", "body"), **common_attributes(data))
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Whatsapp
|
|
4
|
+
module Webhook
|
|
5
|
+
class Message
|
|
6
|
+
# Fallback for a message `type` not in {Message::MESSAGE_TYPES} — either a
|
|
7
|
+
# type Meta added after this gem was released, or a message the Cloud API
|
|
8
|
+
# itself couldn't process (carries an `errors[]` array in that case).
|
|
9
|
+
class Unknown < Base
|
|
10
|
+
# @!attribute [rw] raw
|
|
11
|
+
# @return [Hash] The full, untyped raw message hash.
|
|
12
|
+
attr_accessor :raw
|
|
13
|
+
|
|
14
|
+
# @!attribute [rw] errors
|
|
15
|
+
# @return [Array<Error>]
|
|
16
|
+
attr_accessor :errors
|
|
17
|
+
|
|
18
|
+
def initialize(raw:, errors:, **base_attributes)
|
|
19
|
+
super(**base_attributes)
|
|
20
|
+
|
|
21
|
+
@raw = raw
|
|
22
|
+
@errors = errors
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
class << self
|
|
26
|
+
# @param data [Hash] The raw message hash.
|
|
27
|
+
# @return [Unknown]
|
|
28
|
+
def deserialize(data)
|
|
29
|
+
new(
|
|
30
|
+
raw: data,
|
|
31
|
+
errors: Array(data["errors"]).map { |error_data| Error.deserialize(error_data) },
|
|
32
|
+
**common_attributes(data)
|
|
33
|
+
)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Whatsapp
|
|
4
|
+
module Webhook
|
|
5
|
+
class Message
|
|
6
|
+
# An inbound video message.
|
|
7
|
+
class Video < Media
|
|
8
|
+
class << self
|
|
9
|
+
# @param data [Hash] The raw message hash.
|
|
10
|
+
# @return [Video]
|
|
11
|
+
def deserialize(data)
|
|
12
|
+
new(**media_attributes(data, "video"), **common_attributes(data))
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Whatsapp
|
|
4
|
+
module Webhook
|
|
5
|
+
# Dispatches a single `messages[]` entry from the `messages` webhook field to
|
|
6
|
+
# the class matching its `type`. Mirrors `Whatsapp::Messages::KINDS` — resolution
|
|
7
|
+
# goes through this frozen whitelist (never `const_get` on the `type` string,
|
|
8
|
+
# which comes straight from the internet), so an unrecognized type falls back to
|
|
9
|
+
# {Message::Unknown} rather than raising.
|
|
10
|
+
class Message
|
|
11
|
+
MESSAGE_TYPES = {
|
|
12
|
+
text: Text,
|
|
13
|
+
image: Image,
|
|
14
|
+
video: Video,
|
|
15
|
+
audio: Audio,
|
|
16
|
+
document: Document,
|
|
17
|
+
sticker: Sticker,
|
|
18
|
+
location: Location,
|
|
19
|
+
contacts: Contacts,
|
|
20
|
+
interactive: Interactive,
|
|
21
|
+
button: Button,
|
|
22
|
+
order: Order,
|
|
23
|
+
system: System,
|
|
24
|
+
reaction: Reaction,
|
|
25
|
+
}.freeze
|
|
26
|
+
|
|
27
|
+
class << self
|
|
28
|
+
# @param data [Hash] A raw `messages[]` entry.
|
|
29
|
+
# @return [Message::Base] One of the classes in {MESSAGE_TYPES}, or {Message::Unknown}.
|
|
30
|
+
def deserialize(data)
|
|
31
|
+
data ||= {}
|
|
32
|
+
klass = MESSAGE_TYPES.fetch(data["type"].to_s.to_sym) { Unknown }
|
|
33
|
+
|
|
34
|
+
klass.deserialize(data)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Whatsapp
|
|
4
|
+
module Webhook
|
|
5
|
+
# Template component modifications (e.g. Meta editing a template's header,
|
|
6
|
+
# body, or button on the business's behalf).
|
|
7
|
+
#
|
|
8
|
+
# Best-effort schema: Meta's public docs describe this field in one line with
|
|
9
|
+
# no published JSON example. Validate against a real payload (App Dashboard
|
|
10
|
+
# "send test payload") before relying on these attribute names in production.
|
|
11
|
+
# Source: https://developers.facebook.com/documentation/business-messaging/whatsapp/webhooks/overview
|
|
12
|
+
class MessageTemplateComponentsUpdate
|
|
13
|
+
# @!attribute [rw] message_template_id
|
|
14
|
+
# @return [Integer, nil]
|
|
15
|
+
attr_accessor :message_template_id
|
|
16
|
+
|
|
17
|
+
# @!attribute [rw] message_template_name
|
|
18
|
+
# @return [String, nil]
|
|
19
|
+
attr_accessor :message_template_name
|
|
20
|
+
|
|
21
|
+
# @!attribute [rw] message_template_language
|
|
22
|
+
# @return [String, nil]
|
|
23
|
+
attr_accessor :message_template_language
|
|
24
|
+
|
|
25
|
+
# @!attribute [rw] message_template_element
|
|
26
|
+
# @return [String, nil] The component that changed, e.g. `"BODY"`.
|
|
27
|
+
attr_accessor :message_template_element
|
|
28
|
+
|
|
29
|
+
def initialize(message_template_id:, message_template_name:, message_template_language:,
|
|
30
|
+
message_template_element:)
|
|
31
|
+
@message_template_id = message_template_id
|
|
32
|
+
@message_template_name = message_template_name
|
|
33
|
+
@message_template_language = message_template_language
|
|
34
|
+
@message_template_element = message_template_element
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
class << self
|
|
38
|
+
# @param data [Hash] The raw `value` hash.
|
|
39
|
+
# @return [MessageTemplateComponentsUpdate]
|
|
40
|
+
def deserialize(data)
|
|
41
|
+
data ||= {}
|
|
42
|
+
|
|
43
|
+
new(
|
|
44
|
+
message_template_id: data["message_template_id"],
|
|
45
|
+
message_template_name: data["message_template_name"],
|
|
46
|
+
message_template_language: data["message_template_language"],
|
|
47
|
+
message_template_element: data["message_template_element"]
|
|
48
|
+
)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Whatsapp
|
|
4
|
+
module Webhook
|
|
5
|
+
# Template quality score changes (e.g. green/yellow/red rating shifts based
|
|
6
|
+
# on recipient feedback).
|
|
7
|
+
#
|
|
8
|
+
# Best-effort schema: Meta's public docs describe this field in one line with
|
|
9
|
+
# no published JSON example. Validate against a real payload (App Dashboard
|
|
10
|
+
# "send test payload") before relying on these attribute names in production.
|
|
11
|
+
# Source: https://developers.facebook.com/documentation/business-messaging/whatsapp/webhooks/overview
|
|
12
|
+
class MessageTemplateQualityUpdate
|
|
13
|
+
# @!attribute [rw] message_template_id
|
|
14
|
+
# @return [Integer, nil]
|
|
15
|
+
attr_accessor :message_template_id
|
|
16
|
+
|
|
17
|
+
# @!attribute [rw] message_template_name
|
|
18
|
+
# @return [String, nil]
|
|
19
|
+
attr_accessor :message_template_name
|
|
20
|
+
|
|
21
|
+
# @!attribute [rw] message_template_language
|
|
22
|
+
# @return [String, nil]
|
|
23
|
+
attr_accessor :message_template_language
|
|
24
|
+
|
|
25
|
+
# @!attribute [rw] previous_quality_score
|
|
26
|
+
# @return [String, nil] e.g. `"GREEN"`, `"YELLOW"`, `"RED"`.
|
|
27
|
+
attr_accessor :previous_quality_score
|
|
28
|
+
|
|
29
|
+
# @!attribute [rw] new_quality_score
|
|
30
|
+
# @return [String, nil]
|
|
31
|
+
attr_accessor :new_quality_score
|
|
32
|
+
|
|
33
|
+
def initialize(message_template_id:, message_template_name:, message_template_language:,
|
|
34
|
+
previous_quality_score:, new_quality_score:)
|
|
35
|
+
@message_template_id = message_template_id
|
|
36
|
+
@message_template_name = message_template_name
|
|
37
|
+
@message_template_language = message_template_language
|
|
38
|
+
@previous_quality_score = previous_quality_score
|
|
39
|
+
@new_quality_score = new_quality_score
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
class << self
|
|
43
|
+
# @param data [Hash] The raw `value` hash.
|
|
44
|
+
# @return [MessageTemplateQualityUpdate]
|
|
45
|
+
def deserialize(data)
|
|
46
|
+
data ||= {}
|
|
47
|
+
|
|
48
|
+
new(
|
|
49
|
+
message_template_id: data["message_template_id"],
|
|
50
|
+
message_template_name: data["message_template_name"],
|
|
51
|
+
message_template_language: data["message_template_language"],
|
|
52
|
+
previous_quality_score: data["previous_quality_score"],
|
|
53
|
+
new_quality_score: data["new_quality_score"]
|
|
54
|
+
)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Whatsapp
|
|
4
|
+
module Webhook
|
|
5
|
+
# Template status modifications — approved, rejected, flagged, paused, or
|
|
6
|
+
# disabled by Meta.
|
|
7
|
+
# Source: https://developers.facebook.com/documentation/business-messaging/whatsapp/webhooks/overview
|
|
8
|
+
class MessageTemplateStatusUpdate
|
|
9
|
+
# @!attribute [rw] message_template_id
|
|
10
|
+
# @return [Integer, nil]
|
|
11
|
+
attr_accessor :message_template_id
|
|
12
|
+
|
|
13
|
+
# @!attribute [rw] message_template_name
|
|
14
|
+
# @return [String, nil]
|
|
15
|
+
attr_accessor :message_template_name
|
|
16
|
+
|
|
17
|
+
# @!attribute [rw] message_template_language
|
|
18
|
+
# @return [String, nil]
|
|
19
|
+
attr_accessor :message_template_language
|
|
20
|
+
|
|
21
|
+
# @!attribute [rw] event
|
|
22
|
+
# @return [String, nil] e.g. `"APPROVED"`, `"REJECTED"`, `"FLAGGED"`, `"PAUSED"`, `"DISABLED"`.
|
|
23
|
+
attr_accessor :event
|
|
24
|
+
|
|
25
|
+
# @!attribute [rw] reason
|
|
26
|
+
# @return [String, nil]
|
|
27
|
+
attr_accessor :reason
|
|
28
|
+
|
|
29
|
+
def initialize(message_template_id:, message_template_name:, message_template_language:, event:, reason: nil)
|
|
30
|
+
@message_template_id = message_template_id
|
|
31
|
+
@message_template_name = message_template_name
|
|
32
|
+
@message_template_language = message_template_language
|
|
33
|
+
@event = event
|
|
34
|
+
@reason = reason
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
class << self
|
|
38
|
+
# @param data [Hash] The raw `value` hash.
|
|
39
|
+
# @return [MessageTemplateStatusUpdate]
|
|
40
|
+
def deserialize(data)
|
|
41
|
+
data ||= {}
|
|
42
|
+
|
|
43
|
+
new(
|
|
44
|
+
message_template_id: data["message_template_id"],
|
|
45
|
+
message_template_name: data["message_template_name"],
|
|
46
|
+
message_template_language: data["message_template_language"],
|
|
47
|
+
event: data["event"],
|
|
48
|
+
reason: data["reason"]
|
|
49
|
+
)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|