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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +276 -634
- data/docs/README.md +73 -0
- data/docs/business_phone_number/README.md +232 -0
- data/docs/business_phone_number/account.md +170 -0
- data/docs/business_phone_number/profile.md +220 -0
- data/docs/configuration.md +172 -0
- data/docs/errors.md +208 -0
- data/docs/media/README.md +161 -0
- data/docs/message_templates/README.md +206 -0
- data/docs/message_templates/authentication.md +107 -0
- data/docs/message_templates/carousel.md +103 -0
- data/docs/message_templates/components.md +179 -0
- data/docs/message_templates/library.md +98 -0
- data/docs/message_templates/limited_time_offer.md +94 -0
- data/docs/message_templates/responses.md +173 -0
- data/docs/message_templates/standard.md +138 -0
- data/docs/messages/README.md +135 -0
- data/docs/messages/address.md +86 -0
- data/docs/messages/audio.md +43 -0
- data/docs/messages/contacts.md +129 -0
- data/docs/messages/document.md +49 -0
- data/docs/messages/image.md +59 -0
- data/docs/messages/interactive.md +281 -0
- data/docs/messages/location.md +51 -0
- data/docs/messages/location_request.md +59 -0
- data/docs/messages/mark_message_as_read.md +84 -0
- data/docs/messages/reaction.md +59 -0
- data/docs/messages/sticker.md +40 -0
- data/docs/messages/template.md +166 -0
- data/docs/messages/text.md +55 -0
- data/docs/messages/video.md +41 -0
- data/docs/subscribed_app/README.md +139 -0
- data/docs/webhooks/README.md +209 -0
- data/docs/webhooks/account_alerts.md +44 -0
- data/docs/webhooks/account_review_update.md +29 -0
- data/docs/webhooks/account_update.md +54 -0
- data/docs/webhooks/automatic_events.md +47 -0
- data/docs/webhooks/business_capability_update.md +40 -0
- data/docs/webhooks/history.md +44 -0
- data/docs/webhooks/message_template_components_update.md +46 -0
- data/docs/webhooks/message_template_quality_update.md +49 -0
- data/docs/webhooks/message_template_status_update.md +55 -0
- data/docs/webhooks/messages.md +385 -0
- data/docs/webhooks/partner_solutions.md +35 -0
- data/docs/webhooks/payment_configuration_update.md +40 -0
- data/docs/webhooks/phone_number_name_update.md +44 -0
- data/docs/webhooks/phone_number_quality_update.md +40 -0
- data/docs/webhooks/security.md +43 -0
- data/docs/webhooks/smb_app_state_sync.md +53 -0
- data/docs/webhooks/smb_message_echoes.md +54 -0
- data/docs/webhooks/template_category_update.md +52 -0
- data/docs/webhooks/user_preferences.md +48 -0
- data/lib/ruby/whatsapp/business_phone_number/account/details.rb +149 -0
- data/lib/ruby/whatsapp/business_phone_number/account/get.rb +53 -0
- data/lib/ruby/whatsapp/business_phone_number/account/transport.rb +30 -0
- data/lib/ruby/whatsapp/business_phone_number/account/update.rb +76 -0
- data/lib/ruby/whatsapp/business_phone_number/account.rb +23 -0
- data/lib/ruby/whatsapp/business_phone_number/profile/details.rb +105 -0
- data/lib/ruby/whatsapp/business_phone_number/profile/get.rb +56 -0
- data/lib/ruby/whatsapp/business_phone_number/profile/update.rb +148 -0
- data/lib/ruby/whatsapp/business_phone_number/profile/verticals.rb +54 -0
- data/lib/ruby/whatsapp/business_phone_number/profile.rb +22 -0
- data/lib/ruby/whatsapp/business_phone_number/response.rb +3 -3
- data/lib/ruby/whatsapp/business_phone_number/transport.rb +11 -12
- data/lib/ruby/whatsapp/business_phone_number.rb +11 -4
- data/lib/ruby/whatsapp/message_templates.rb +2 -6
- data/lib/ruby/whatsapp/path_building.rb +33 -0
- data/lib/ruby/whatsapp/subscribed_app/transport.rb +6 -5
- data/lib/ruby/whatsapp/version.rb +1 -1
- 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
|
|
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},
|
|
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
|
-
# {
|
|
7
|
-
#
|
|
8
|
-
#
|
|
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 "
|
|
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
|
-
|
|
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.
|
|
12
|
-
# {Whatsapp::
|
|
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
|
-
#
|
|
17
|
-
#
|
|
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
|
-
|
|
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
|
-
|
|
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
|
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.
|
|
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
|