diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ccb8e1..cecf5df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # Unreleased +- Implement a Better API for calling the Cloud API [156](https://github.com/ignacio-chiazzo/ruby_whatsapp_sdk/pull/156) - Used [VCR gem]() for tests @igacio-chiazzo [153](https://github.com/ignacio-chiazzo/ruby_whatsapp_sdk/pull/153) +- Added support for API v20.0 and v21.0 @guizaols [152](https://github.com/ignacio-chiazzo/ruby_whatsapp_sdk/pull/152) - Increased minimum required Ruby version to 2.7.0 @ignacio-chiazzo [151](https://github.com/ignacio-chiazzo/ruby_whatsapp_sdk/pull/151) # v 0.13.0 diff --git a/README.md b/README.md index a62c673..ac44a58 100644 --- a/README.md +++ b/README.md @@ -35,11 +35,7 @@ There are three primary resources, `Messages`, `Media` and `PhoneNumbers`. `Mess To use `Messages`, `Media` or `PhoneNumbers`, you need to initialize the `Client` that contains auth information. There are two ways to do it. -1. Use an initializer - -Note: -Optionally, you can specify the desired API version to use (defaults to the latest version if omitted). -Available API version can be found [here](https://developers.facebook.com/docs/graph-api/changelog/versions). +#### Option 1) Use an initializer ```ruby # config/initializers/whatsapp_sdk.rb @@ -50,22 +46,26 @@ WhatsappSdk.configure do |config| config.logger_options = { bodies: true } # optional, they are all valid logger_options for Faraday end ``` -More Details on Faraday Logger Options are [here](https://lostisland.github.io/faraday/#/middleware/included/logging?id=logging). -OR 2) Create a `Client` instance and pass it to the `Messages`, `Medias` or `PhoneNumbers` instance like this: +Notes: +- Optionally, you can specify the desired API version to use (defaults to the latest version if omitted). +Available API version can be found [here](https://developers.facebook.com/docs/graph-api/changelog/versions). +- You can attach a logger. More Details on Faraday Logger Options are [here](https://lostisland.github.io/faraday/#/middleware/included/logging?id=logging). + + +#### Option 2) Create a `Client` instance : -**Without Logger:** ```ruby + +# without client = WhatsappSdk::Api::Client.new("") # replace this with a valid access token -messages_api = WhatsappSdk::Api::Messages.new(client) -``` -**With Logger:** -```ruby + +# OR optionally use a logger, api_version and logger = Logger.new(STDOUT) logger_options = { bodies: true } -client = WhatsappSdk::Api::Client.new("", "", logger, logger_options) # replace this with a valid access token -messages_api = WhatsappSdk::Api::Messages.new(client) +client = WhatsappSdk::Api::Client.new("", "", logger, logger_options) ``` + Each API operation returns a `WhatsappSdk::Api::Response` that contains `data` and `error` and a couple of helpful functions such as `ok?` and `error?`. There are three types of responses `WhatsappSdk::Api::MessageDataResponse`, `WhatsappSdk::Api::PhoneNumberDataResponse` and `WhatsappSdk::Api::PhoneNumbersDataResponse`. Each of them contains different attributes. ## Set up a Meta app @@ -119,15 +119,13 @@ end Phone Numbers API ```ruby -phone_numbers_api = WhatsappSdk::Api::PhoneNumbers.new -registered_number = phone_numbers_api.registered_number(SENDER_ID) +registered_number = client.phone_numbers.registered_number(SENDER_ID) ``` Messages API ```ruby -messages_api = WhatsappSdk::Api::Messages.new -message_sent = messages_api.send_text(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, +message_sent = client.messages.send_text(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, message: "Hey there! it's Whatsapp Ruby SDK") ``` @@ -135,20 +133,6 @@ Check the [example.rb file](https://github.com/ignacio-chiazzo/ruby_whatsapp_sdk -## Operations - -First, create the client and then create an instance `WhatsappSdk::Api::Messages` that requires a client as a param like this: - -```ruby -messages_api = WhatsappSdk::Api::Messages.new -phone_numbers_api = WhatsappSdk::Api::PhoneNumbers.new -medias_api = WhatsappSdk::Api::Medias.new -business_profile_api = WhatsappSdk::Api::BusinessProfile.new -templates_api = WhatsappSdk::Api::Templates.new -``` - -Note: Remember to initialize the client first! - ## APIs ### Templates @@ -157,64 +141,52 @@ Note: Remember to initialize the client first! ```ruby # Get list of templates -templates_api.templates(business_id: BUSINESS_ID) +client.templates.list(business_id: BUSINESS_ID) + +# Get Message Template Namespace +# The message template namespace is required to send messages using the message templates. +client.templates.get_message_template_namespace(business_id: BUSINESS_ID) # Create a template -new_template = templates_api.create( +client.templates.create( business_id: BUSINESS_ID, name: "seasonal_promotion", language: "en_US", category: "MARKETING", components_json: components_json, allow_category_change: true ) # Delete a template -templates_api.delete(business_id: BUSINESS_ID, name: "my_name") # delete by name +client.templates.delete(business_id: BUSINESS_ID, name: "my_name") # delete by name ``` - ### Business Profile API
-Get the details of your business - ```ruby -business_profile = business_profile_api.details(123456) -``` - -Update the details of your business +# Get the details of your business +client.business_profiles.get(phone_number_id) -```ruby -business_profile_api.update(phone_number_id: SENDER_ID, params: { about: "A very cool business" } ) +# Update the details of your business +client.business_profiles.update(phone_number_id: SENDER_ID, params: { about: "A very cool business" } ) ``` -
### Phone numbers API
-Get the list of phone numbers registered - ```ruby -phone_numbers_api.registered_numbers(123456) # accepts a business_id -``` +# Get the list of phone numbers registered +client.phone_numbers.list(business_id) -Get the a phone number by id +# Get the a phone number by id +client.phone_numbers.get(phone_number_id) -```ruby -phone_numbers_api.registered_numbers(123456) # accepts a phone_number_id -``` +# Register a phone number +client.phone_numbers.register_number(phone_number_id, pin) -Register a phone number - -```ruby -phone_numbers_api.register_number(phone_number_id, pin) -``` - -Deregister a phone number - -```ruby -phone_numbers_api.deregister_number(phone_number_id) +# Deregister a phone number +client.phone_numbers.deregister_number(phone_number_id) ```
@@ -223,148 +195,96 @@ phone_numbers_api.deregister_number(phone_number_id)
-Upload a media - ```ruby -medias_api.upload(sender_id: SENDER_ID, file_path: "tmp/whatsapp.png", type: "image/png") -``` +# Upload a media +client.media.upload(sender_id: SENDER_ID, file_path: "tmp/whatsapp.png", type: "image/png") -Get a media - -```ruby -media = medias_api.media(media_id: MEDIA_ID) -``` +# Get a media +media = client.media.get(media_id: MEDIA_ID) -Download media +# Download media +client.media.download(url: MEDIA_URL, file_path: 'tmp/downloaded_whatsapp.png', media_type: "image/png") -```ruby -medias_api.download(url: MEDIA_URL, file_path: 'tmp/downloaded_whatsapp.png', media_type: "image/png") +# Delete a media +client.media.delete(media_id: MEDIA_ID) ``` - -Delete a media - -```ruby -medias_api.delete(media_id: MEDIA_ID) -``` -
### Messages API
-**Send a text message** - ```ruby -messages_api.send_text(sender_id: 1234, recipient_number: 112345678, message: "hola") -``` +# Send a text message +client.messages.send_text(sender_id: 1234, recipient_number: 112345678, message: "hola") -**Read a message** +# Read a message +client.messages.read_message(sender_id: 1234, message_id: "wamid.HBgLMTM0M12345678910=") -```ruby -messages_api.read_message(sender_id: 1234, message_id: "wamid.HBgLMTM0M12345678910=") -``` +# Note: To get the `message_id` you can set up [Webhooks](https://developers.facebook.com/docs/whatsapp/cloud-api/webhooks/components) that will listen and fire an event when a message is received. -Note: To get the `message_id` you can set up [Webhooks](https://developers.facebook.com/docs/whatsapp/cloud-api/webhooks/components) that will listen and fire an event when a message is received. - -**Send a reaction to message** -To send a reaction to a message, you need to obtain the message id and look for the emoji's unicode you want to use. - -```ruby -messages_api.send_reaction(sender_id: 123_123, recipient_number: 56_789, message_id: "12345", emoji: "\u{1f550}") - -messages_api.send_reaction(sender_id: 123_123, recipient_number: 56_789, message_id: "12345", emoji: "⛄️") -``` +# Send a reaction to message +# To send a reaction to a message, you need to obtain the message id and look for the emoji's unicode you want to use. +client.messages.send_reaction(sender_id: 123_123, recipient_number: 56_789, message_id: "12345", emoji: "\u{1f550}") +client.messages.send_reaction(sender_id: 123_123, recipient_number: 56_789, message_id: "12345", emoji: "⛄️") -**Reply to a message** -To reply to a message, just include the id of the message in the `messages_api` methods. For example, to reply to a text message include the following: +# Reply to a message +# To reply to a message, just include the id of the message in the `client.messages` methods. For example, to reply to a text message include the following: +client.messages.send_text(sender_id: 123_123, recipient_number: 56_789, message: "I'm a reply", message_id: "wamid.1234") -```ruby -messages_api.send_text(sender_id: 123_123, recipient_number: 56_789, message: "I'm a reply", message_id: "wamid.1234") -``` - -**Send a location message** - -```ruby -messages_api.send_location( +# Send a location message +client.messages.send_location( sender_id: 123123, recipient_number: 56789, longitude: 45.4215, latitude: 75.6972, name: "nacho", address: "141 cooper street" ) -``` - -**Send an image message** -It could use a link or an image_id. -```ruby -# with a link -messages_api.send_image( - sender_id: 123123, recipient_number: 56789, link: "image_link", caption: "Ignacio Chiazzo Profile" -) +# Send an image message +# It uses a link or an image_id. +# with a link +client.messages.send_image(sender_id: 123123, recipient_number: 56789, link: "image_link", caption: "Ignacio Chiazzo Profile") # with an image id -messages_api.send_image( - sender_id: 123123, recipient_number: 56789, image_id: "1234", caption: "Ignacio Chiazzo Profile" -) -``` +client.messages.send_image(sender_id: 123123, recipient_number: 56789, image_id: "1234", caption: "Ignacio Chiazzo Profile") -**Send an audio message** -It could use a link or an audio_id. -```ruby +# Send an audio message +# It uses a link or an audio_id. # with a link -messages_api.send_audio(sender_id: 123123, recipient_number: 56789, link: "audio_link") +client.messages.send_audio(sender_id: 123123, recipient_number: 56789, link: "audio_link") # with an audio id -messages_api.send_audio(sender_id: 123123, recipient_number: 56789, audio_id: "1234") -``` - -**Send a document message** -It could use a link or a document_id. +client.messages.send_audio(sender_id: 123123, recipient_number: 56789, audio_id: "1234") -```ruby +# Send a document message +# It uses a link or a document_id. # with a link -messages_api.send_document( - sender_id: 123123, recipient_number: 56789, link: "document_link", caption: "Ignacio Chiazzo" -) +client.messages.send_document(sender_id: 123123, recipient_number: 56789, link: "document_link", caption: "Ignacio Chiazzo") # with a document id -messages_api.send_document( - sender_id: 123123, recipient_number: 56789, document_id: "1234", caption: "Ignacio Chiazzo" -) -``` - -Note, you can specify the filename via file [`filename` argument](https://developers.facebook.com/docs/whatsapp/cloud-api/reference/messages). +client.messages.send_document(sender_id: 123123, recipient_number: 56789, document_id: "1234", caption: "Ignacio Chiazzo") +# Note, you can specify the filename via argument [`filename`](https://developers.facebook.com/docs/whatsapp/cloud-api/reference/messages). -**Send a sticker message** -It could use a link or a sticker_id. - -```ruby -# with a link -messages_api.send_sticker(sender_id: 123123, recipient_number: 56789, link: "link") +# Send a sticker message +# It could use a link or a sticker_id. +# with a link +client.messages.send_sticker(sender_id: 123123, recipient_number: 56789, link: "link") # with a sticker_id -messages_api.send_sticker(sender_id: 123123, recipient_number: 56789, sticker_id: "1234") -``` +client.messages.send_sticker(sender_id: 123123, recipient_number: 56789, sticker_id: "1234") -**Send contacts message** -To send a contact, you need to create a Contact instance object that contain objects embedded like `addresses`, `birthday`, `emails`, `name`, `org`. See this [guide](/test/contact_helper.rb) to learn how to create contacts objects. +# Send contacts message +# To send a contact, you need to create a Contact instance object that contain objects embedded like `addresses`, `birthday`, `emails`, `name`, `org`. See this [guide](/test/contact_helper.rb) to learn how to create contacts objects. +client.messages.send_contacts(sender_id: 123123, recipient_number: 56789, contacts: [create_contact(params)]) -```ruby -contacts = [create_contact(params)] -messages_api.send_contacts(sender_id: 123123, recipient_number: 56789, contacts: contacts) -``` +# Alternatively, you could pass a plain json like this: +client.messages.send_contacts(sender_id: 123123, recipient_number: 56789, contacts_json: {...}) -Alternatively, you could pass a plain json like this: +# Send a template message +# WhatsApp message templates are specific message formats that businesses use to send out notifications or customer care messages to people that have opted in to notifications. Messages can include appointment reminders, shipping information, issue resolution or payment updates. -```ruby -messages_api.send_contacts(sender_id: 123123, recipient_number: 56789, contacts_json: {...}) +# Before sending a message template, you need to create one. visit the [Official API Documentation](https://developers.facebook.com/docs/whatsapp/cloud-api/guides/send-message-templates) ``` -**Send a template message** -WhatsApp message templates are specific message formats that businesses use to send out notifications or customer care messages to people that have opted in to notifications. Messages can include appointment reminders, shipping information, issue resolution or payment updates. - -**Before sending a message template, you need to create one.** visit the [Official API Documentation](https://developers.facebook.com/docs/whatsapp/cloud-api/guides/send-message-templates) -
Component's example ```ruby @@ -407,7 +327,7 @@ button_component2 = WhatsappSdk::Resource::Component.new( ) location_component = WhatsappSdk::Resource::Component.new(type: "header", parameters: [parameter_location]) -@messages_api.send_template(sender_id: 12_345, recipient_number: 12345678, name: "hello_world", language: "en_US", components_json: [component_1]) +client.messages.send_template(sender_id: 12_345, recipient_number: 12345678, name: "hello_world", language: "en_US", components_json: [component_1]) ```
@@ -415,7 +335,7 @@ location_component = WhatsappSdk::Resource::Component.new(type: "header", parame Alternatively, you could pass a plain json like this: ```ruby -@messages_api.send_template(sender_id: 12_345, recipient_number: 12345678, name: "hello_world", language: "en_US", components_json: [{...}]) +client.messages.send_template(sender_id: 12_345, recipient_number: 12345678, name: "hello_world", language: "en_US", components_json: [{...}]) ``` **Send interactive messages** @@ -449,7 +369,7 @@ interactive_list_messages = WhatsappSdk::Resource::Interactive.new( action: interactive_action ) -messages_api.send_interactive_list_messages( +client.messages.send_interactive_list_messages( sender_id: 12_345, recipient_number: 1234567890, interactive: interactive_list_messages ) @@ -460,7 +380,7 @@ messages_api.send_interactive_list_messages( Alternatively, you could pass a plain json like this: ```ruby -messages_api.send_interactive_list_messages( +client.messages.send_interactive_list_messages( sender_id: 12_345, recipient_number: 1234567890 interactive_json: {...} ) @@ -495,7 +415,7 @@ interactive_reply_buttons = WhatsappSdk::Resource::Interactive.new( action: interactive_action ) -messages_api.send_interactive_reply_buttons( +client.messages.send_interactive_reply_buttons( sender_id: 12_345, recipient_number: 1234567890, interactive: interactive_reply_buttons ) @@ -506,7 +426,7 @@ messages_api.send_interactive_reply_buttons( Alternative, you could pass a plain json like this: ```ruby -messages_api.send_interactive_reply_buttons( +client.messages.send_interactive_reply_buttons( sender_id: 12_345, recipient_number: 1234567890 interactive_json: {...} ) diff --git a/example.rb b/example.rb index 765785c..e2568ef 100644 --- a/example.rb +++ b/example.rb @@ -33,7 +33,7 @@ exit end -puts "\n\n\n\n\n\n *************** Starting calling the Cloud API *************** \n" +puts "\n\n\n\ ------------------ Starting calling the Cloud API -------------------\n" ################# Initialize Client ################# WhatsappSdk.configure do |config| @@ -41,11 +41,11 @@ end ################# HELPERS ######################## -def print_message_sent(message_response) +def print_message_sent(message_response, type = "") if message_response.ok? - puts "Message sent to: #{message_response.data.contacts.first.input}" + puts "Message #{type} sent to: #{message_response.data.contacts.first.input}" else - puts "Error: #{message_response.error&.to_s}" + puts "Error: #{message_response.error.message}" end end @@ -57,21 +57,19 @@ def print_data_or_error(response, identifier) return identifier end ################################################## +client = WhatsappSdk::Api::Client.new -medias_api = WhatsappSdk::Api::Medias.new -messages_api = WhatsappSdk::Api::Messages.new -phone_numbers_api = WhatsappSdk::Api::PhoneNumbers.new -business_profile_api = WhatsappSdk::Api::BusinessProfile.new -templates_api = WhatsappSdk::Api::Templates.new ############################## Templates API ############################## +puts "\n\n ------------------ Testing Templates API ------------------------" + ## Get list of templates -templates = templates_api.templates(business_id: BUSINESS_ID) +templates = client.templates.list(business_id: BUSINESS_ID) puts "GET Templates list : #{print_data_or_error(templates, templates.data&.templates.map { |r| r.template.name })}" ## Get message templates namespace -template_namespace = templates_api.get_message_template_namespace(business_id: BUSINESS_ID) +template_namespace = client.templates.get_message_template_namespace(business_id: BUSINESS_ID) puts "GET template by namespace: #{print_data_or_error(template_namespace, template_namespace.data&.id)}" # Create a template @@ -104,7 +102,7 @@ def print_data_or_error(response, identifier) } ] -new_template = templates_api.create( +new_template = client.templates.create( business_id: BUSINESS_ID, name: "seasonal_promotion", language: "ka", category: "MARKETING", components_json: components_json, allow_category_change: true ) @@ -124,171 +122,200 @@ def print_data_or_error(response, identifier) ] } ] -updated_template = templates_api.update(template_id: "1624560287967996", category: "UTILITY") -puts "UPDATE template by id: #{print_data_or_error(updated_template, updated_template.data&.id)}" + +if new_template&.data&.id + updated_template = client.templates.update(template_id: new_template&.data.id, category: "UTILITY") + puts "UPDATE template by id: #{print_data_or_error(updated_template, updated_template.data&.id)}" +end ## Delete a template -delete_template = templates_api.delete(business_id: BUSINESS_ID, name: "seasonal_promotion") # delete by name -puts "DELETE template by id: #{print_data_or_error(delete_template, delete_template.data&.id) }" -# templates_api.delete(business_id: BUSINESS_ID, name: "name2", hsm_id: "243213188351928") # delete by name and id +delete_template = client.templates.delete(business_id: BUSINESS_ID, name: "seasonal_promotion") # delete by name +puts "Delete template by id: #{print_data_or_error(delete_template, delete_template.data&.id) }" + +# client.templates.delete(business_id: BUSINESS_ID, name: "name2", hsm_id: "243213188351928") # delete by name and id + + ############################## Business API ############################## -business_profile = business_profile_api.details(SENDER_ID) +puts "\n\n\n ------------------ Testing Business API -----------------------" + +business_profile = client.business_profiles.get(SENDER_ID) puts "DELETE Business Profile by id: #{print_data_or_error(delete_template, business_profile.data&.about) }" -updated_bp = business_profile_api.update(phone_number_id: SENDER_ID, params: { about: "A very cool business" } ) +updated_bp = client.business_profiles.update(phone_number_id: SENDER_ID, params: { about: "A very cool business" } ) puts "UPDATE Business Profile by id: #{print_data_or_error(updated_bp, updated_bp.data&.success?) }" + ############################## Phone Numbers API ############################## -registered_number = phone_numbers_api.registered_number(SENDER_ID) +puts "\n\n\n ------------------ Testing Phone Numbers API -----------------------" +registered_number = client.phone_numbers.get(SENDER_ID) puts "GET Registered number: #{print_data_or_error(registered_number, registered_number.data&.id)}" -registered_numbers = phone_numbers_api.registered_numbers(BUSINESS_ID) +registered_numbers = client.phone_numbers.list(BUSINESS_ID) puts "GET Registered numbers: #{print_data_or_error(registered_number, registered_numbers.data&.phone_numbers.map(&:id))}" ############################## Media API ############################## - +puts "\n\n\n ------------------ Testing Media API" ##### Image ##### # upload a Image -uploaded_media = medias_api.upload(sender_id: SENDER_ID, file_path: "test/fixtures/assets/whatsapp.png", type: "image/png") -puts "Uploaded media id: #{print_data_or_error(uploaded_media, uploaded_media.data&.id)}" +uploaded_media = client.media.upload(sender_id: SENDER_ID, file_path: "test/fixtures/assets/whatsapp.png", type: "image/png") +puts "Uploaded image id: #{print_data_or_error(uploaded_media, uploaded_media.data&.id)}" # get a media Image if uploaded_media.data&.id - media = medias_api.media(media_id: 1753306975419607) - puts "GET Media id: #{print_data_or_error(media, media.data&.id)}" + image = client.media.get(media_id: uploaded_media.data&.id) + puts "GET image id: #{print_data_or_error(image, image.data&.id)}" # download media Image - download_image = medias_api.download(url: media.data.url, file_path: 'test/fixtures/assets/downloaded_image.png', media_type: "image/png") - puts "Downloaded: #{print_data_or_error(download_image, download_image.data.success?)}" + download_image = client.media.download(url: image.data.url, file_path: 'test/fixtures/assets/downloaded_image.png', media_type: "image/png") + puts "Downloaded Image: #{print_data_or_error(download_image, download_image.data.success?)}" + uploaded_media = client.media.upload(sender_id: SENDER_ID, file_path: "test/fixtures/assets/whatsapp.png", type: "image/png") # delete a media - deleted_media = medias_api.delete(media_id: media.data.id) - puts "DELETE: #{print_data_or_error(deleted_media, deleted_media.data.success?)}" + deleted_media = client.media.delete(media_id: uploaded_media.data.id) + puts "Delete image: #{print_data_or_error(deleted_media, deleted_media.data.success?)}" else puts "No media to download and delete" end #### Video #### # upload a video -uploaded_media = medias_api.upload(sender_id: SENDER_ID, file_path: "test/fixtures/assets/riquelme.mp4", type: "video/mp4") -puts "Uploaded media id: #{print_data_or_error(uploaded_media, uploaded_media.data&.id)}" +uploaded_video = client.media.upload(sender_id: SENDER_ID, file_path: "test/fixtures/assets/riquelme.mp4", type: "video/mp4") +puts "Uploaded video: #{print_data_or_error(uploaded_media, uploaded_video.data&.id)}" -media = medias_api.media(media_id: "535689082735659") +video = client.media.get(media_id: uploaded_video.data&.id) # upload a video -uploaded_video = medias_api.upload(sender_id: SENDER_ID, file_path: "test/fixtures/assets/riquelme.mp4", type: "video/mp4") -puts "Uploaded media id: #{print_data_or_error(uploaded_media, uploaded_media.data&.id)}" - -media = medias_api.media(media_id: "535689082735659") +uploaded_video = client.media.upload(sender_id: SENDER_ID, file_path: "test/fixtures/assets/riquelme.mp4", type: "video/mp4") +puts "Uploaded video id: #{print_data_or_error(uploaded_media, video.data&.id)}" #### Audio #### # upload an audio -uploaded_media = medias_api.upload(sender_id: SENDER_ID, file_path: "test/fixtures/assets/downloaded_audio.ogg", type: "audio/ogg") -puts "Uploaded media id: #{print_data_or_error(uploaded_media, uploaded_media.data&.id)}" - -if uploaded_media.data&.id - media_id = uploaded_media.data&.id - puts "Uploaded media id: #{media_id}" +audio_response = client.media.upload(sender_id: SENDER_ID, file_path: "test/fixtures/assets/downloaded_audio.ogg", type: "audio/ogg") +puts "Uploaded audio id: #{print_data_or_error(audio_response, audio_response.data&.id)}" +if audio_response.data&.id + audio_id = audio_response.data&.id # get a media audio - media = medias_api.media(media_id: media_id) - puts "GET Media id: #{print_data_or_error(media, media_id)}" + audio = client.media.get(media_id: audio_id) + puts "GET Audio id: #{print_data_or_error(audio, audio_id)}" # get a media audio - audio_link = media.data.url - download_image = medias_api.download(url: audio_link, file_path: 'test/fixtures/assets/downloaded_audio2.ogg', media_type: "audio/ogg") - puts "Download Media Audio: #{print_data_or_error(download_image, download_image.data.success?)}" + audio_link = audio.data.url + download_image = client.media.download(url: audio_link, file_path: 'test/fixtures/assets/downloaded_audio2.ogg', media_type: "audio/ogg") + puts "Download Audio: #{print_data_or_error(download_image, download_image.data.success?)}" end +# upload a document +document_response = client.media.upload(sender_id: SENDER_ID, file_path: "test/fixtures/assets/document.pdf", type: "application/pdf") +puts "Uploaded document id: #{print_data_or_error(document_response, document_response.data&.id)}" + +document = client.media.get(media_id: document_response.data&.id) +puts "GET document id: #{print_data_or_error(document, document.data&.id)}" + +# upload a sticker +sticker_response = client.media.upload(sender_id: SENDER_ID, file_path: "test/fixtures/assets/sticker.webp", type: "image/webp") +puts "Uploaded sticker id: #{print_data_or_error(sticker_response, sticker_response.data&.id)}" + +sticker = client.media.get(media_id: sticker_response.data&.id) +puts "GET Sticker id: #{print_data_or_error(sticker, sticker.data&.id)}" + + + ############################## Messages API ############################## +puts "\n\n\n ------------------ Testing Messages API -----------------------" ######### SEND A TEXT MESSAGE -message_sent = messages_api.send_text(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, +message_sent = client.messages.send_text(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, message: "Hey there! it's Whatsapp Ruby SDK") -print_message_sent(message_sent) +print_message_sent(message_sent, "text") ######### React to a message -message_id = message_sent.data.messages.first.id -reaction_1_sent = messages_api.send_reaction( +message_id = message_sent.data&.messages.first.id +reaction_1_sent = client.messages.send_reaction( sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, message_id: message_id, emoji: "\u{1f550}" - ) +) if message_id -reaction_2_sent = messages_api.send_reaction(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, - message_id: message_id, emoji: "⛄️") +reaction_2_sent = client.messages.send_reaction(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, + message_id: message_id, emoji: "⛄️") if message_id puts "Message Reaction 1: #{print_data_or_error(reaction_1_sent, reaction_1_sent.data&.messages.first&.id)}" puts "Message Reaction 2: #{print_data_or_error(reaction_2_sent, reaction_2_sent.data&.messages.first&.id)}" ######### Reply to a message message_to_reply_id = message_sent.data.messages.first.id -reply = messages_api.send_text(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, message: "I'm a reply", +reply = client.messages.send_text(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, message: "I'm a reply", message_id: message_to_reply_id) -print_message_sent(reply) +print_message_sent(reply, "reply") ######### Send location -location_sent = messages_api.send_location( + +location_sent = client.messages.send_location( sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, longitude: -75.6898604, latitude: 45.4192206, name: "Ignacio", address: "My house" ) -print_message_sent(location_sent) +print_message_sent(location_sent, "location") ######### READ A MESSAGE -# messages_api.read_message(sender_id: SENDER_ID, message_id: msg_id) +# client.messages.read_message(sender_id: SENDER_ID, message_id: msg_id) ######### SEND AN IMAGE # Send an image with a link -if media.data&.id - image_sent = messages_api.send_image( - sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, link: media.data.url, caption: "Ignacio Chiazzo Profile" +if image.data&.id + image_sent = client.messages.send_image( + sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, link: image.data.url, caption: "Ignacio Chiazzo Profile" ) - print_message_sent(image_sent) + print_message_sent(image_sent, "image via url") # Send an image with an id - messages_api.send_image( - sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, image_id: media.data.id, caption: "Ignacio Chiazzo Profile" + client.messages.send_image( + sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, image_id: image.data.id, caption: "Ignacio Chiazzo Profile" ) - print_message_sent(image_sent) + print_message_sent(image_sent, "image via id") end ######### SEND AUDIOS ## with a link -audio_sent = messages_api.send_audio(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, link: "audio_link") -print_message_sent(audio_sent) +audio_sent = client.messages.send_audio(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, link: audio.data.url) +print_message_sent(audio_sent, "audio via url") ## with an audio id -audio_sent = messages_api.send_audio(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, audio_id: "1234") -print_message_sent(audio_sent) +audio_sent = client.messages.send_audio(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, audio_id: audio.data.id) +print_message_sent(audio_sent, "audio via id") ######### SEND DOCUMENTS ## with a link -document_sent = messages_api.send_document( - sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, link: "document_link", caption: "Ignacio Chiazzo" -) -print_message_sent(document_sent) +if document.data&.id + document_sent = client.messages.send_document( + sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, link: document.data&.url, caption: "Ignacio Chiazzo" + ) + print_message_sent(document_sent, "document via url") -## with a document id -document_sent = messages_api.send_document( - sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, document_id: "1234", caption: "Ignacio Chiazzo" -) -print_message_sent(document_sent) + ## with a document id + document_sent = client.messages.send_document( + sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, document_id: document.data&.id, caption: "Ignacio Chiazzo" + ) # modify + print_message_sent(document_sent, "document via id") +end ######### SEND STICKERS -## with a link -sticker_sent = messages_api.send_sticker(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, link: "link") -print_message_sent(sticker_sent) - -## with a sticker_id -sticker_sent = messages_api.send_sticker(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, sticker_id: "1234") -print_message_sent(sticker_sent) +if sticker.data&.id + ## with a link + sticker_sent = client.messages.send_sticker(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, link: sticker.data.url) + print_message_sent(sticker_sent, "sticker via url") + + ## with a sticker_id + sticker_sent = client.messages.send_sticker(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, sticker_id: sticker.data.id) + print_message_sent(sticker_sent, "sticker via id") +end ######### SEND A TEMPLATE # Note: The template must have been created previously. # Send a template with no component -response_with_object = messages_api.send_template(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, +response_with_object = client.messages.send_template(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, name: "hello_world", language: "en_US", components: []) puts response_with_object @@ -361,7 +388,7 @@ def print_data_or_error(response, identifier) ) # Send a template with component_json -response_with_json = messages_api.send_template( +response_with_json = client.messages.send_template( sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, name: "hello_world", language: "en_US", components_json: [ { @@ -418,7 +445,7 @@ def print_data_or_error(response, identifier) action: interactive_action ) -messages_api.send_interactive_reply_buttons( +client.messages.send_interactive_reply_buttons( sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER, interactive: interactive_reply_buttons ) diff --git a/lib/whatsapp_sdk/api/business_profile.rb b/lib/whatsapp_sdk/api/business_profile.rb index 34dfb38..052cabd 100644 --- a/lib/whatsapp_sdk/api/business_profile.rb +++ b/lib/whatsapp_sdk/api/business_profile.rb @@ -23,7 +23,7 @@ def initialize(vertical:) # # @param phone_number_id [Integer] Phone Number Id. # @return [Api::Response] Response object. - def details(phone_number_id, fields: nil) + def get(phone_number_id, fields: nil) fields = if fields fields.join(',') else @@ -41,6 +41,11 @@ def details(phone_number_id, fields: nil) ) end + def details(phone_number_id, fields: nil) + warn "[DEPRECATION] `details` is deprecated. Please use `get` instead." + get(phone_number_id, fields: fields) + end + # Update the details of business profile. # # @param phone_number_id [Integer] Phone Number Id. diff --git a/lib/whatsapp_sdk/api/client.rb b/lib/whatsapp_sdk/api/client.rb index 9900f11..3736039 100644 --- a/lib/whatsapp_sdk/api/client.rb +++ b/lib/whatsapp_sdk/api/client.rb @@ -14,7 +14,7 @@ class Client ].freeze def initialize( - access_token, + access_token = WhatsappSdk.configuration.access_token, api_version = ApiConfiguration::DEFAULT_API_VERSION, logger = nil, logger_options = {} @@ -27,6 +27,26 @@ def initialize( @api_version = api_version end + def media + @media ||= WhatsappSdk::Api::Medias.new + end + + def messages + @messages ||= WhatsappSdk::Api::Messages.new + end + + def phone_numbers + @phone_numbers ||= WhatsappSdk::Api::PhoneNumbers.new + end + + def business_profiles + @business_profiles ||= WhatsappSdk::Api::BusinessProfile.new + end + + def templates + @templates ||= WhatsappSdk::Api::Templates.new + end + def send_request(endpoint: "", full_url: nil, http_method: "post", params: {}, headers: {}, multipart: false) url = full_url || "#{ApiConfiguration::API_URL}/#{@api_version}/" diff --git a/lib/whatsapp_sdk/api/medias.rb b/lib/whatsapp_sdk/api/medias.rb index a9350e0..75e3f0b 100644 --- a/lib/whatsapp_sdk/api/medias.rb +++ b/lib/whatsapp_sdk/api/medias.rb @@ -38,7 +38,7 @@ def initialize(media_type:) # # @param media_id [String] Media Id. # @return [Api::Response] Response object. - def media(media_id:) + def get(media_id:) response = send_request( http_method: "get", endpoint: "/#{media_id}" @@ -50,6 +50,11 @@ def media(media_id:) ) end + def media(media_id:) + warn "[DEPRECATION] `media` is deprecated. Please use `get` instead." + get(media_id: media_id) + end + # Download Media by URL. # # @param url URL. diff --git a/lib/whatsapp_sdk/api/phone_numbers.rb b/lib/whatsapp_sdk/api/phone_numbers.rb index ea6f782..147a5b7 100644 --- a/lib/whatsapp_sdk/api/phone_numbers.rb +++ b/lib/whatsapp_sdk/api/phone_numbers.rb @@ -16,7 +16,7 @@ class PhoneNumbers < Request # # @param business_id [Integer] Business Id. # @return [Api::Response] Response object. - def registered_numbers(business_id) + def list(business_id) response = send_request( http_method: "get", endpoint: "#{business_id}/phone_numbers?fields=#{DEFAULT_FIELDS}" @@ -28,11 +28,11 @@ def registered_numbers(business_id) ) end - # Get the registered number id. + # Get the registered number. # # @param phone_number_id [Integer] The registered number we want to retrieve. # @return [Api::Response] Response object. - def registered_number(phone_number_id) + def get(phone_number_id) response = send_request( http_method: "get", endpoint: "#{phone_number_id}?fields=#{DEFAULT_FIELDS}" @@ -78,6 +78,17 @@ def deregister_number(phone_number_id) data_class_type: Api::Responses::PhoneNumberDataResponse ) end + + # deprecated methods + def registered_numbers(business_id) + warn "[DEPRECATION] `registered_numbers` is deprecated. Please use `list` instead." + list(business_id) + end + + def registered_number(phone_number_id) + warn "[DEPRECATION] `registered_number` is deprecated. Please use `get` instead." + get(phone_number_id) + end end end end diff --git a/lib/whatsapp_sdk/api/request.rb b/lib/whatsapp_sdk/api/request.rb index d415158..53362bd 100644 --- a/lib/whatsapp_sdk/api/request.rb +++ b/lib/whatsapp_sdk/api/request.rb @@ -1,6 +1,8 @@ # typed: true # frozen_string_literal: true +require_relative "../../whatsapp_sdk" + module WhatsappSdk module Api class Request diff --git a/lib/whatsapp_sdk/api/templates.rb b/lib/whatsapp_sdk/api/templates.rb index 4e7d144..4767188 100644 --- a/lib/whatsapp_sdk/api/templates.rb +++ b/lib/whatsapp_sdk/api/templates.rb @@ -75,7 +75,7 @@ def create( # @param business_id [Integer] The business ID. # @param limit [Integer] Optional. Number of templates to return in a single page. # @return [Response] Response object. - def templates(business_id:, limit: 100) + def list(business_id:, limit: 100) params = {} params["limit"] = limit if limit @@ -92,6 +92,11 @@ def templates(business_id:, limit: 100) ) end + def templates(business_id:) + warn "[DEPRECATION] `templates` is deprecated. Please use `list` instead." + list(business_id: business_id) + end + # Get Message Template Namespace # The message template namespace is required to send messages using the message templates. # diff --git a/test/whatsapp/api/business_profile_test.rb b/test/whatsapp/api/business_profile_test.rb index d60f8ca..b0b8789 100644 --- a/test/whatsapp/api/business_profile_test.rb +++ b/test/whatsapp/api/business_profile_test.rb @@ -15,26 +15,26 @@ def setup @business_profile_api = BusinessProfile.new(client) end - def test_details_handles_error_response + def test_get_handles_error_response VCR.use_cassette('business_profile/details_handles_error_response') do - response = @business_profile_api.details(123_123) + response = @business_profile_api.get(123_123) assert_unsupported_request_error("get", response, "123123", "AYMXgC3SR8dC_HM7lrwoPOZ") end end - def test_details_accepts_fields + def test_get_accepts_fields fields = %w[vertical] VCR.use_cassette('business_profile/details_accepts_fields') do - response = @business_profile_api.details(107_878_721_936_019, fields: fields) + response = @business_profile_api.get(107_878_721_936_019, fields: fields) assert_ok_response(response) assert_equal(%w[vertical messaging_product], response.raw_response["data"][0].keys) end end - def test_details_sends_all_fields_by_default + def test_get_sends_all_fields_by_default VCR.use_cassette('business_profile/details_sends_all_fields_by_default') do - response = @business_profile_api.details(107_878_721_936_019) + response = @business_profile_api.get(107_878_721_936_019) assert_business_details_response( { @@ -51,9 +51,9 @@ def test_details_sends_all_fields_by_default end end - def test_details_with_success_response + def test_get_with_success_response VCR.use_cassette('business_profile/details_with_success_response') do - response = @business_profile_api.details(107_878_721_936_019) + response = @business_profile_api.get(107_878_721_936_019) assert_business_details_response( { diff --git a/test/whatsapp/api/client_test.rb b/test/whatsapp/api/client_test.rb index 47b586c..39ed27a 100644 --- a/test/whatsapp/api/client_test.rb +++ b/test/whatsapp/api/client_test.rb @@ -9,7 +9,9 @@ module WhatsappSdk module Api class ClientTest < Minitest::Test def setup(api_version: ApiConfiguration::DEFAULT_API_VERSION) - @client = Client.new('test_token', api_version) + @access_token = 'test_token' + @api_version = api_version + @client = Client.new(@access_token, @api_version) end def test_send_request_post_with_success_response @@ -100,6 +102,26 @@ def test_should_not_log_when_logger_not_configured refute_includes(middleware_handlers, Faraday::Response::Logger) end + def test_media + assert_equal(WhatsappSdk::Api::Medias, @client.media.class) + end + + def test_messages + assert_equal(WhatsappSdk::Api::Messages, @client.messages.class) + end + + def test_phone_numbers + assert_equal(WhatsappSdk::Api::PhoneNumbers, @client.phone_numbers.class) + end + + def test_business_profiles + assert_equal(WhatsappSdk::Api::BusinessProfile, @client.business_profiles.class) + end + + def test_templates + assert_equal(WhatsappSdk::Api::Templates, @client.templates.class) + end + private def stub_test_request(method_name, body: {}, headers: {}, response_status: 200, response_body: { success: true }, diff --git a/test/whatsapp/api/medias_test.rb b/test/whatsapp/api/medias_test.rb index 241d6fe..bd3b387 100644 --- a/test/whatsapp/api/medias_test.rb +++ b/test/whatsapp/api/medias_test.rb @@ -17,16 +17,16 @@ def setup @sender_id = 107_878_721_936_019 end - def test_media_handles_error_response + def test_get_handles_error_response VCR.use_cassette("medias/media_handles_error_response") do - response = @medias_api.media(media_id: "123_123") + response = @medias_api.get(media_id: "123_123") assert_unsupported_request_error("get", response, "123_123", "ATf5-CLoxGyJeSu2vrRDOZR") end end - def test_media_with_success_response + def test_get_with_success_response VCR.use_cassette("medias/media_with_success_response") do - response = @medias_api.media(media_id: "1761991787669262") + response = @medias_api.get(media_id: "1761991787669262") assert_media_response({ url: "https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=1761991787669262&ext=1728904986&hash=ATta-PkMyBz0aTF9b0CVDimLtAkAgpdXQa6t5x1KgUOu-Q", diff --git a/test/whatsapp/api/phone_numbers_test.rb b/test/whatsapp/api/phone_numbers_test.rb index 975b137..28a9b65 100644 --- a/test/whatsapp/api/phone_numbers_test.rb +++ b/test/whatsapp/api/phone_numbers_test.rb @@ -16,23 +16,23 @@ def setup @phone_numbers_api = PhoneNumbers.new(client) end - def test_registered_numbers_handles_error_response + def test_list_handles_error_response VCR.use_cassette('phone_numbers/registered_numbers_handles_error_response') do - response = @phone_numbers_api.registered_numbers(123_123) + response = @phone_numbers_api.list(123_123) assert_unsupported_request_error("get", response, "123123", "AFZgW89DkR0hLRFJP40NTd6") end end - def test_registered_numbers_with_success_response + def test_list_with_success_response VCR.use_cassette('phone_numbers/registered_numbers_with_success_response') do - response = @phone_numbers_api.registered_numbers(114_503_234_599_312) + response = @phone_numbers_api.list(114_503_234_599_312) expected_phone_numbers = [registered_phone_number] assert_phone_numbers_success_response(expected_phone_numbers, response) end end - def test_registered_numbers_sends_valid_params + def test_list_sends_valid_params @phone_numbers_api.expects(:send_request).with( http_method: "get", endpoint: "123123/phone_numbers?fields=#{PhoneNumbers::DEFAULT_FIELDS}" @@ -43,24 +43,24 @@ def test_registered_numbers_sends_valid_params } ) - @phone_numbers_api.registered_numbers(123_123) + @phone_numbers_api.list(123_123) end - def test_registered_number_handles_error_response + def test_get_handles_error_response VCR.use_cassette('phone_numbers/registered_number_handles_error_response') do - response = @phone_numbers_api.registered_number(123_123) + response = @phone_numbers_api.get(123_123) assert_unsupported_request_error("get", response, "123123", "AlicHjOpoShf8TV_iXRm1pW") end end - def test_registered_number_with_success_response + def test_get_with_success_response VCR.use_cassette('phone_numbers/registered_number_with_success_response') do - response = @phone_numbers_api.registered_number(107_878_721_936_019) + response = @phone_numbers_api.get(107_878_721_936_019) assert_phone_number_success_response(registered_phone_number, response) end end - def test_registered_number_sends_valid_params + def test_get_sends_valid_params @phone_numbers_api.expects(:send_request).with( http_method: "get", endpoint: "123123?fields=#{PhoneNumbers::DEFAULT_FIELDS}" @@ -68,7 +68,7 @@ def test_registered_number_sends_valid_params { "data" => [registered_phone_number] } ) - @phone_numbers_api.registered_number(123_123) + @phone_numbers_api.get(123_123) end def test_register_number_handles_error_response diff --git a/test/whatsapp/api/templates_test.rb b/test/whatsapp/api/templates_test.rb index fb8dcc8..f3a5a02 100644 --- a/test/whatsapp/api/templates_test.rb +++ b/test/whatsapp/api/templates_test.rb @@ -67,7 +67,7 @@ def test_create_a_template_with_valid_params_and_components ##### GET Templates def test_get_templates VCR.use_cassette('templates/get_templates') do - templates_response = @templates_api.templates(business_id: 114_503_234_599_312) + templates_response = @templates_api.list(business_id: 114_503_234_599_312) assert_ok_response(templates_response) assert_equal(Responses::TemplatesDataResponse, templates_response.data.class) assert_equal(25, templates_response.data.templates.size) @@ -77,7 +77,7 @@ def test_get_templates def test_get_templates_when_an_error_is_returned VCR.use_cassette('templates/get_templates_when_an_error_is_returned') do - templates_response = @templates_api.templates(business_id: 123_456) + templates_response = @templates_api.list(business_id: 123_456) assert_unsupported_request_error("get", templates_response, "123456", "AhvemSTIjTs-WJikZKj0mLu") end end