ruby-whatsapp 0.4.0 → 0.4.2

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.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -0
  3. data/README.md +276 -634
  4. data/docs/README.md +73 -0
  5. data/docs/business_phone_number/README.md +232 -0
  6. data/docs/business_phone_number/account.md +170 -0
  7. data/docs/business_phone_number/profile.md +220 -0
  8. data/docs/configuration.md +172 -0
  9. data/docs/errors.md +208 -0
  10. data/docs/media/README.md +161 -0
  11. data/docs/message_templates/README.md +206 -0
  12. data/docs/message_templates/authentication.md +107 -0
  13. data/docs/message_templates/carousel.md +103 -0
  14. data/docs/message_templates/components.md +179 -0
  15. data/docs/message_templates/library.md +98 -0
  16. data/docs/message_templates/limited_time_offer.md +94 -0
  17. data/docs/message_templates/responses.md +173 -0
  18. data/docs/message_templates/standard.md +138 -0
  19. data/docs/messages/README.md +135 -0
  20. data/docs/messages/address.md +86 -0
  21. data/docs/messages/audio.md +43 -0
  22. data/docs/messages/contacts.md +129 -0
  23. data/docs/messages/document.md +49 -0
  24. data/docs/messages/image.md +59 -0
  25. data/docs/messages/interactive.md +281 -0
  26. data/docs/messages/location.md +51 -0
  27. data/docs/messages/location_request.md +59 -0
  28. data/docs/messages/mark_message_as_read.md +84 -0
  29. data/docs/messages/reaction.md +59 -0
  30. data/docs/messages/sticker.md +40 -0
  31. data/docs/messages/template.md +166 -0
  32. data/docs/messages/text.md +55 -0
  33. data/docs/messages/video.md +41 -0
  34. data/docs/subscribed_app/README.md +139 -0
  35. data/docs/webhooks/README.md +209 -0
  36. data/docs/webhooks/account_alerts.md +44 -0
  37. data/docs/webhooks/account_review_update.md +29 -0
  38. data/docs/webhooks/account_update.md +54 -0
  39. data/docs/webhooks/automatic_events.md +47 -0
  40. data/docs/webhooks/business_capability_update.md +40 -0
  41. data/docs/webhooks/history.md +44 -0
  42. data/docs/webhooks/message_template_components_update.md +46 -0
  43. data/docs/webhooks/message_template_quality_update.md +49 -0
  44. data/docs/webhooks/message_template_status_update.md +55 -0
  45. data/docs/webhooks/messages.md +385 -0
  46. data/docs/webhooks/partner_solutions.md +35 -0
  47. data/docs/webhooks/payment_configuration_update.md +40 -0
  48. data/docs/webhooks/phone_number_name_update.md +44 -0
  49. data/docs/webhooks/phone_number_quality_update.md +40 -0
  50. data/docs/webhooks/security.md +43 -0
  51. data/docs/webhooks/smb_app_state_sync.md +53 -0
  52. data/docs/webhooks/smb_message_echoes.md +54 -0
  53. data/docs/webhooks/template_category_update.md +52 -0
  54. data/docs/webhooks/user_preferences.md +48 -0
  55. data/lib/ruby/whatsapp/business_phone_number/account/details.rb +149 -0
  56. data/lib/ruby/whatsapp/business_phone_number/account/get.rb +53 -0
  57. data/lib/ruby/whatsapp/business_phone_number/account/transport.rb +30 -0
  58. data/lib/ruby/whatsapp/business_phone_number/account/update.rb +76 -0
  59. data/lib/ruby/whatsapp/business_phone_number/account.rb +23 -0
  60. data/lib/ruby/whatsapp/business_phone_number/profile/details.rb +105 -0
  61. data/lib/ruby/whatsapp/business_phone_number/profile/get.rb +56 -0
  62. data/lib/ruby/whatsapp/business_phone_number/profile/update.rb +148 -0
  63. data/lib/ruby/whatsapp/business_phone_number/profile/verticals.rb +54 -0
  64. data/lib/ruby/whatsapp/business_phone_number/profile.rb +22 -0
  65. data/lib/ruby/whatsapp/business_phone_number/response.rb +3 -3
  66. data/lib/ruby/whatsapp/business_phone_number/transport.rb +11 -12
  67. data/lib/ruby/whatsapp/business_phone_number.rb +11 -4
  68. data/lib/ruby/whatsapp/message_templates.rb +2 -6
  69. data/lib/ruby/whatsapp/path_building.rb +33 -0
  70. data/lib/ruby/whatsapp/subscribed_app/transport.rb +6 -5
  71. data/lib/ruby/whatsapp/version.rb +1 -1
  72. metadata +63 -1
@@ -0,0 +1,148 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Whatsapp
4
+ module BusinessPhoneNumber
5
+ module Profile
6
+ # Updates a business profile: its about text, description, contact details, websites,
7
+ # industry vertical, and profile picture.
8
+ #
9
+ # A validated instance rather than a bare class method (unlike {Get}, which has nothing
10
+ # to check): Meta documents a closed vertical enum and per-field character limits, and
11
+ # since every field is optional an all-nil call would spend a request to change nothing.
12
+ # Source: https://developers.facebook.com/documentation/business-messaging/whatsapp/reference/whatsapp-business-phone-number/whatsapp-business-profile-api
13
+ class Update
14
+ include ActiveModel::Validations
15
+ extend ResponseHandling
16
+ extend Transport
17
+
18
+ module Defaults
19
+ MESSAGING_PRODUCT = "whatsapp"
20
+ EDGE = "whatsapp_business_profile"
21
+ end
22
+
23
+ # The character and count limits Meta documents for a business profile.
24
+ module Limits
25
+ ABOUT = 139
26
+ ADDRESS = 256
27
+ DESCRIPTION = 512
28
+ EMAIL = 128
29
+ WEBSITES = 2
30
+ end
31
+
32
+ # Every updatable field, in payload order. Drives both the "change something"
33
+ # guard and its message, so the two cannot drift apart.
34
+ ATTRIBUTES = %i[about address description email vertical websites profile_picture_handle].freeze
35
+
36
+ # @!attribute [rw] about
37
+ # @return [String, nil] The profile's about text, at most {Limits::ABOUT} characters.
38
+ attr_accessor :about
39
+
40
+ # @!attribute [rw] address
41
+ # @return [String, nil] The business's address, at most {Limits::ADDRESS} characters.
42
+ attr_accessor :address
43
+
44
+ # @!attribute [rw] description
45
+ # @return [String, nil] The business description, at most {Limits::DESCRIPTION} characters.
46
+ attr_accessor :description
47
+
48
+ # @!attribute [rw] email
49
+ # @return [String, nil] The contact email, at most {Limits::EMAIL} characters.
50
+ attr_accessor :email
51
+
52
+ # @!attribute [rw] vertical
53
+ # @return [String, nil] One of {Verticals::ALL}.
54
+ attr_accessor :vertical
55
+
56
+ # @!attribute [rw] websites
57
+ # @return [Array<String>, nil] At most {Limits::WEBSITES} URLs.
58
+ attr_accessor :websites
59
+
60
+ # @!attribute [rw] profile_picture_handle
61
+ # @return [String, nil] A picture handle from Meta's Resumable Upload API.
62
+ attr_accessor :profile_picture_handle
63
+
64
+ validate :validate_any_attribute_present
65
+ validate :validate_websites_limit
66
+ validates :about, length: { maximum: Limits::ABOUT }, allow_nil: true
67
+ validates :address, length: { maximum: Limits::ADDRESS }, allow_nil: true
68
+ validates :description, length: { maximum: Limits::DESCRIPTION }, allow_nil: true
69
+ validates :email, length: { maximum: Limits::EMAIL }, allow_nil: true
70
+ validates :vertical, inclusion: { in: Verticals::ALL }, allow_nil: true
71
+ validates :profile_picture_handle, presence: true, allow_nil: true
72
+
73
+ # @param about [String, nil] See {#about}.
74
+ # @param address [String, nil] See {#address}.
75
+ # @param description [String, nil] See {#description}.
76
+ # @param email [String, nil] Length only — Meta validates the address itself
77
+ # server-side, and a format check here would reject valid exotic addresses.
78
+ # @param vertical [String, Symbol, nil] One of {Verticals::ALL}, either casing.
79
+ # @param websites [Array<String>, nil] At most {Limits::WEBSITES} URLs. An empty
80
+ # array is a deliberate instruction to clear the list, not an omission.
81
+ # @param profile_picture_handle [String, nil] Opaque to this gem; presence only.
82
+ # @raise [ActiveModel::ValidationError] if every field is nil, or one breaks a
83
+ # documented limit.
84
+ def initialize(about: nil, address: nil, description: nil, email: nil, vertical: nil,
85
+ websites: nil, profile_picture_handle: nil)
86
+ @about = about
87
+ @address = address
88
+ @description = description
89
+ @email = email
90
+ @vertical = Verticals.normalize(vertical)
91
+ @websites = websites
92
+ @profile_picture_handle = profile_picture_handle
93
+
94
+ validate!
95
+ end
96
+
97
+ # @return [Hash] The update payload. `messaging_product` is documented required so it
98
+ # is always sent; every other field is optional and an omitted one is compacted away
99
+ # rather than sent as null, which Meta would read as an instruction to blank it.
100
+ # An empty `websites` array survives compaction on purpose — that *is* the clear.
101
+ def serialize
102
+ { messaging_product: Defaults::MESSAGING_PRODUCT, about:, address:, description:,
103
+ email:, vertical:, websites:, profile_picture_handle:, }.compact
104
+ end
105
+
106
+ class << self
107
+ # @param client [Whatsapp::Client] The WhatsApp client instance.
108
+ # @param about [String, nil] See {#initialize}.
109
+ # @param address [String, nil] See {#initialize}.
110
+ # @param description [String, nil] See {#initialize}.
111
+ # @param email [String, nil] See {#initialize}.
112
+ # @param vertical [String, Symbol, nil] See {#initialize}.
113
+ # @param websites [Array<String>, nil] See {#initialize}.
114
+ # @param profile_picture_handle [String, nil] See {#initialize}.
115
+ # @return [BusinessPhoneNumber::Response]
116
+ # @raise [ActiveModel::ValidationError] if no field is given, or one is invalid.
117
+ # @raise [Error] if no phone number ID is configured, or the request fails.
118
+ def call(client: Client.new, about: nil, address: nil, description: nil, email: nil,
119
+ vertical: nil, websites: nil, profile_picture_handle: nil)
120
+ body = new(about:, address:, description:, email:, vertical:, websites:,
121
+ profile_picture_handle:).serialize
122
+ response = client.connection.post(edge_path(client, Defaults::EDGE), json: body)
123
+
124
+ BusinessPhoneNumber::Response.deserialize(
125
+ parse_json(handle_response!(response, error_class: Error, action: "update business profile"))
126
+ )
127
+ end
128
+ end
129
+
130
+ private
131
+
132
+ # @return [void]
133
+ def validate_any_attribute_present
134
+ return if ATTRIBUTES.any? { |attribute| !public_send(attribute).nil? }
135
+
136
+ errors.add(:base, "at least one of #{ATTRIBUTES.join(', ')} must be provided")
137
+ end
138
+
139
+ # @return [void]
140
+ def validate_websites_limit
141
+ return if websites.nil? || websites.size <= Limits::WEBSITES
142
+
143
+ errors.add(:base, "websites accepts at most #{Limits::WEBSITES} URLs")
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Whatsapp
4
+ module BusinessPhoneNumber
5
+ module Profile
6
+ # The industry verticals Meta publishes for a business profile.
7
+ #
8
+ # Its own file rather than nested inside {Update}, since two classes use it: {Update}
9
+ # validates against it and {Details} exposes the raw value for comparison against it.
10
+ # That follows {Whatsapp::MessageTemplates::Categories}' precedent rather than
11
+ # {Register::DataLocalizationRegions}', which has a single consumer.
12
+ # Source: https://developers.facebook.com/documentation/business-messaging/whatsapp/reference/whatsapp-business-phone-number/whatsapp-business-profile-api
13
+ module Verticals
14
+ ALCOHOL = "ALCOHOL"
15
+ APPAREL = "APPAREL"
16
+ AUTO = "AUTO"
17
+ BEAUTY = "BEAUTY"
18
+ EDU = "EDU"
19
+ ENTERTAIN = "ENTERTAIN"
20
+ EVENT_PLAN = "EVENT_PLAN"
21
+ FINANCE = "FINANCE"
22
+ GOVT = "GOVT"
23
+ GROCERY = "GROCERY"
24
+ HEALTH = "HEALTH"
25
+ HOTEL = "HOTEL"
26
+ NONPROFIT = "NONPROFIT"
27
+ ONLINE_GAMBLING = "ONLINE_GAMBLING"
28
+ OTC_DRUGS = "OTC_DRUGS"
29
+ OTHER = "OTHER"
30
+ PHYSICAL_GAMBLING = "PHYSICAL_GAMBLING"
31
+ PROF_SERVICES = "PROF_SERVICES"
32
+ RESTAURANT = "RESTAURANT"
33
+ RETAIL = "RETAIL"
34
+ TRAVEL = "TRAVEL"
35
+
36
+ ALL = [ALCOHOL, APPAREL, AUTO, BEAUTY, EDU, ENTERTAIN, EVENT_PLAN, FINANCE, GOVT,
37
+ GROCERY, HEALTH, HOTEL, NONPROFIT, ONLINE_GAMBLING, OTC_DRUGS, OTHER,
38
+ PHYSICAL_GAMBLING, PROF_SERVICES, RESTAURANT, RETAIL, TRAVEL,].freeze
39
+
40
+ # Normalizes caller input to a canonical uppercase vertical.
41
+ # Unrecognized values are returned untouched so the inclusion validator can
42
+ # report them, matching {Register::DataLocalizationRegions.normalize}.
43
+ # @param value [String, Symbol, nil]
44
+ # @return [String, nil]
45
+ def self.normalize(value)
46
+ return if value.nil?
47
+
48
+ candidate = value.to_s.upcase
49
+ ALL.include?(candidate) ? candidate : value.to_s
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Whatsapp
4
+ module BusinessPhoneNumber
5
+ # Reads and updates a business phone number's **business profile** — the public card a
6
+ # WhatsApp user sees before they reply: the about line, description, address, email,
7
+ # websites, industry vertical, and profile picture.
8
+ #
9
+ # Unlike {Account}, this is not an exception to the module's `phone_id` rule: Meta exposes
10
+ # the profile as an edge on the phone number itself
11
+ # (`GET`/`POST /{phone_id}/whatsapp_business_profile`), so {Get} and {Update} address the
12
+ # same ID the onboarding actions do and reuse {BusinessPhoneNumber::Transport} unchanged.
13
+ #
14
+ # Distinct from {Account}, which describes the *account* a number belongs to rather than
15
+ # how that number presents itself, and from {Whatsapp::Messages}, which is what actually
16
+ # reaches a user once the profile is set.
17
+ # See `docs/business_phone_number/profile.md`.
18
+ # Source: https://developers.facebook.com/documentation/business-messaging/whatsapp/reference/whatsapp-business-phone-number/whatsapp-business-profile-api
19
+ module Profile
20
+ end
21
+ end
22
+ end
@@ -2,11 +2,11 @@
2
2
 
3
3
  module Whatsapp
4
4
  module BusinessPhoneNumber
5
- # The response shared by all four phone-number actions: `{success}`, with an
5
+ # The response shared by every write action in this module: `{success}`, with an
6
6
  # optional `id` that only `VerifyCode` ever populates. One class covers all of
7
7
  # them — unlike {Whatsapp::SubscribedApp}'s `Response::*` namespace — since
8
- # {Register}, {Deregister}, {RequestCode}, and {VerifyCode} all return this same
9
- # shape, `id` included or not.
8
+ # {Register}, {Deregister}, {RequestCode}, {VerifyCode}, {Account::Update}, and
9
+ # {Profile::Update} all return this same shape, `id` included or not.
10
10
  # Source: https://developers.facebook.com/documentation/business-messaging/whatsapp/business-phone-numbers/registration
11
11
  class Response
12
12
  # @!attribute [rw] success
@@ -2,26 +2,25 @@
2
2
 
3
3
  module Whatsapp
4
4
  module BusinessPhoneNumber
5
- # The one piece shared by {Register}, {Deregister}, {RequestCode}, and
6
- # {VerifyCode}: all four address the same phone-number-scoped resource, differing
7
- # only in edge name and body. Extended (not included) because {#edge_path} is used
8
- # from class-level `.call` methods (as a private class method).
5
+ # The one piece shared by {Register}, {Deregister}, {RequestCode}, {VerifyCode}, and
6
+ # {Profile}: all of them address a phone-number-scoped edge, differing only in edge name
7
+ # and body. Extended (not included) because {#edge_path} is used from class-level `.call`
8
+ # methods (as a private class method).
9
+ #
10
+ # The guard itself and its message live in {Whatsapp::PathBuilding}, shared with every
11
+ # other ID-scoped feature; what stays here is the ID this module addresses.
9
12
  module Transport
13
+ include Whatsapp::PathBuilding
14
+
10
15
  private
11
16
 
12
17
  # @param client [Whatsapp::Client]
13
18
  # @param action [String] The edge to address ("register", "deregister",
14
- # "request_code", or "verify_code").
19
+ # "request_code", "verify_code", or "whatsapp_business_profile").
15
20
  # @return [String] The versioned path to the phone number's action edge.
16
21
  # @raise [Error] if no phone number ID is configured.
17
22
  def edge_path(client, action)
18
- if client.phone_id.nil? || client.phone_id.to_s.empty?
19
- raise Error,
20
- "phone_id is required for the #{action} edge; " \
21
- "set it via Whatsapp.configure or Client.new(phone_id:)"
22
- end
23
-
24
- client.path_for(client.phone_id, action)
23
+ scoped_path(client, :phone_id, action, error_class: Error, purpose: "the #{action} edge")
25
24
  end
26
25
  end
27
26
  end
@@ -8,13 +8,20 @@ module Whatsapp
8
8
  # the first place. It is a different concern from {Whatsapp::SubscribedApp}, which
9
9
  # turns webhook delivery on and off for a whole WhatsApp Business Account: this
10
10
  # module is per phone number and is a prerequisite for messaging itself, not just
11
- # for notifications. Addresses `phone_id`, like {Whatsapp::Media} and
12
- # {Whatsapp::Messages}, not `waba_id`.
11
+ # for notifications. The onboarding actions address `phone_id`, like
12
+ # {Whatsapp::Media} and {Whatsapp::Messages}.
13
13
  #
14
14
  # The full flow, in order: {RequestCode} -> {VerifyCode} -> {Register}, with
15
15
  # {Deregister} as the reverse switch.
16
- # See `lib/ruby/whatsapp/business_phone_number/CLAUDE.md` and
17
- # `docs/business-phone-number-api.md`.
16
+ #
17
+ # {Profile} reads and updates the public card a WhatsApp user sees before they reply.
18
+ # It addresses `phone_id` like the onboarding actions above, so it shares their transport.
19
+ #
20
+ # {Account} is the one exception to the `phone_id` rule: it reads and updates the
21
+ # WhatsApp Business Account a number belongs to, so it addresses `waba_id` and
22
+ # carries its own transport.
23
+ # See `lib/ruby/whatsapp/business_phone_number/CLAUDE.md`,
24
+ # `docs/business_phone_number/README.md`, and `docs/business_phone_number/profile.md`.
18
25
  # Source: https://developers.facebook.com/documentation/business-messaging/whatsapp/business-phone-numbers/registration
19
26
  module BusinessPhoneNumber
20
27
  class Error < Whatsapp::Error; end
@@ -25,6 +25,7 @@ module Whatsapp
25
25
  # templates.find(template_id: created.id).status # => "PENDING"
26
26
  # Source: https://developers.facebook.com/docs/graph-api/reference/whats-app-business-account/message_templates/
27
27
  class MessageTemplates
28
+ include PathBuilding
28
29
  include ResponseHandling
29
30
 
30
31
  class TemplateError < Whatsapp::Error; end
@@ -204,12 +205,7 @@ module Whatsapp
204
205
  # @return [String] The versioned path for a WABA-scoped edge.
205
206
  # @raise [TemplateError] if no WABA ID is configured.
206
207
  def edge_path(edge)
207
- if blank_value?(client.waba_id)
208
- raise TemplateError,
209
- "waba_id is required for template management; set it via Whatsapp.configure or Client.new(waba_id:)"
210
- end
211
-
212
- client.path_for(client.waba_id, edge)
208
+ scoped_path(client, :waba_id, edge, error_class: TemplateError, purpose: "template management")
213
209
  end
214
210
 
215
211
  # @return [Hash] Only the editable fields that were supplied.
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Whatsapp
4
+ # The ID guard and path build shared by every WABA- or phone-number-scoped feature.
5
+ #
6
+ # Each feature keeps its own transport with a named method — {Whatsapp::SubscribedApp::Transport}'s
7
+ # `edge_path`, {Whatsapp::BusinessPhoneNumber::Account::Transport}'s `node_path` — since those
8
+ # names are what keep an edge and a node from being confused at a call site. This holds only
9
+ # the part that was identical across all of them: refusing to address an unconfigured ID, and
10
+ # phrasing that refusal the same way every time.
11
+ module PathBuilding
12
+ private
13
+
14
+ # @param client [Whatsapp::Client]
15
+ # @param id_name [Symbol] The client attribute to address (`:waba_id` or `:phone_id`).
16
+ # @param segments [Array<String>] Edge segments after the ID; pass none to address the node itself.
17
+ # @param error_class [Class] The feature's own error class, never {Whatsapp::RequestError}.
18
+ # @param purpose [String] What the caller was reaching for, e.g. `"subscribed apps"`.
19
+ # @return [String] The versioned path.
20
+ # @raise [Whatsapp::Error] the given error_class, if the ID is not configured.
21
+ def scoped_path(client, id_name, *segments, error_class:, purpose:)
22
+ id = client.public_send(id_name)
23
+
24
+ if id.nil? || id.to_s.empty?
25
+ raise error_class,
26
+ "#{id_name} is required for #{purpose}; " \
27
+ "set it via Whatsapp.configure or Client.new(#{id_name}:)"
28
+ end
29
+
30
+ client.path_for(id, *segments)
31
+ end
32
+ end
33
+ end
@@ -5,18 +5,19 @@ module Whatsapp
5
5
  # The one piece shared by {List}, {Subscribe}, and {Unsubscribe}: all three address
6
6
  # the same WABA-scoped edge, differing only in HTTP verb and body. Extended (not
7
7
  # included) since those classes are class-method-only.
8
+ #
9
+ # The guard itself and its message live in {Whatsapp::PathBuilding}, shared with every
10
+ # other ID-scoped feature; what stays here is the edge this module addresses.
8
11
  module Transport
12
+ include Whatsapp::PathBuilding
13
+
9
14
  private
10
15
 
11
16
  # @param client [Whatsapp::Client]
12
17
  # @return [String] The versioned path to the `subscribed_apps` edge.
13
18
  # @raise [Error] if no WABA ID is configured.
14
19
  def edge_path(client)
15
- if client.waba_id.nil? || client.waba_id.to_s.empty?
16
- raise Error, "waba_id is required for subscribed apps; set it via Whatsapp.configure or Client.new(waba_id:)"
17
- end
18
-
19
- client.path_for(client.waba_id, "subscribed_apps")
20
+ scoped_path(client, :waba_id, "subscribed_apps", error_class: Error, purpose: "subscribed apps")
20
21
  end
21
22
  end
22
23
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Whatsapp
4
- VERSION = "0.4.0"
4
+ VERSION = "0.4.2"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-whatsapp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Raniery
@@ -82,9 +82,70 @@ files:
82
82
  - LICENSE.txt
83
83
  - README.md
84
84
  - Rakefile
85
+ - docs/README.md
86
+ - docs/business_phone_number/README.md
87
+ - docs/business_phone_number/account.md
88
+ - docs/business_phone_number/profile.md
89
+ - docs/configuration.md
90
+ - docs/errors.md
91
+ - docs/media/README.md
92
+ - docs/message_templates/README.md
93
+ - docs/message_templates/authentication.md
94
+ - docs/message_templates/carousel.md
95
+ - docs/message_templates/components.md
96
+ - docs/message_templates/library.md
97
+ - docs/message_templates/limited_time_offer.md
98
+ - docs/message_templates/responses.md
99
+ - docs/message_templates/standard.md
100
+ - docs/messages/README.md
101
+ - docs/messages/address.md
102
+ - docs/messages/audio.md
103
+ - docs/messages/contacts.md
104
+ - docs/messages/document.md
105
+ - docs/messages/image.md
106
+ - docs/messages/interactive.md
107
+ - docs/messages/location.md
108
+ - docs/messages/location_request.md
109
+ - docs/messages/mark_message_as_read.md
110
+ - docs/messages/reaction.md
111
+ - docs/messages/sticker.md
112
+ - docs/messages/template.md
113
+ - docs/messages/text.md
114
+ - docs/messages/video.md
115
+ - docs/subscribed_app/README.md
116
+ - docs/webhooks/README.md
117
+ - docs/webhooks/account_alerts.md
118
+ - docs/webhooks/account_review_update.md
119
+ - docs/webhooks/account_update.md
120
+ - docs/webhooks/automatic_events.md
121
+ - docs/webhooks/business_capability_update.md
122
+ - docs/webhooks/history.md
123
+ - docs/webhooks/message_template_components_update.md
124
+ - docs/webhooks/message_template_quality_update.md
125
+ - docs/webhooks/message_template_status_update.md
126
+ - docs/webhooks/messages.md
127
+ - docs/webhooks/partner_solutions.md
128
+ - docs/webhooks/payment_configuration_update.md
129
+ - docs/webhooks/phone_number_name_update.md
130
+ - docs/webhooks/phone_number_quality_update.md
131
+ - docs/webhooks/security.md
132
+ - docs/webhooks/smb_app_state_sync.md
133
+ - docs/webhooks/smb_message_echoes.md
134
+ - docs/webhooks/template_category_update.md
135
+ - docs/webhooks/user_preferences.md
85
136
  - lib/ruby/whatsapp.rb
86
137
  - lib/ruby/whatsapp/business_phone_number.rb
138
+ - lib/ruby/whatsapp/business_phone_number/account.rb
139
+ - lib/ruby/whatsapp/business_phone_number/account/details.rb
140
+ - lib/ruby/whatsapp/business_phone_number/account/get.rb
141
+ - lib/ruby/whatsapp/business_phone_number/account/transport.rb
142
+ - lib/ruby/whatsapp/business_phone_number/account/update.rb
87
143
  - lib/ruby/whatsapp/business_phone_number/deregister.rb
144
+ - lib/ruby/whatsapp/business_phone_number/profile.rb
145
+ - lib/ruby/whatsapp/business_phone_number/profile/details.rb
146
+ - lib/ruby/whatsapp/business_phone_number/profile/get.rb
147
+ - lib/ruby/whatsapp/business_phone_number/profile/update.rb
148
+ - lib/ruby/whatsapp/business_phone_number/profile/verticals.rb
88
149
  - lib/ruby/whatsapp/business_phone_number/register.rb
89
150
  - lib/ruby/whatsapp/business_phone_number/request_code.rb
90
151
  - lib/ruby/whatsapp/business_phone_number/response.rb
@@ -175,6 +236,7 @@ files:
175
236
  - lib/ruby/whatsapp/messages/template/parameter.rb
176
237
  - lib/ruby/whatsapp/messages/text.rb
177
238
  - lib/ruby/whatsapp/messages/video.rb
239
+ - lib/ruby/whatsapp/path_building.rb
178
240
  - lib/ruby/whatsapp/railtie.rb
179
241
  - lib/ruby/whatsapp/request_error.rb
180
242
  - lib/ruby/whatsapp/response_handling.rb