Code Monkey home page Code Monkey logo

ruby_whatsapp_sdk's Introduction

Ruby Whatsapp SDK

Gem Version CircleCI

The SDK provides a set of operations and classes to use the Whatsapp API. Send stickers, messages, audio, videos, locations, react and reply to messages or just ask for the phone numbers through this library in a few steps!

Demo

MessageAPIDemo.mov

Check the Ruby on Rails Whatsapp example repository that uses this library to send messages.

Installation

Add this line to your application's Gemfile:

gem 'whatsapp_sdk'

And then execute:

$ bundle

Or install it yourself as:

$ gem install whatsapp_sdk

Quick Start

There are three primary resources, Messages, Media and PhoneNumbers. Messages allows users to send any message (text, audio, location, video, image, etc.). Media allows users to manage media, and Phone Numbers enable clients to query the associated phone numbers.

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.

# config/initializers/whatsapp_sdk.rb
WhatsappSdk.configure do |config|
  config.access_token = ACCESS_TOKEN
  config.api_version = API_VERSION
  config.logger = Logger.new(STDOUT) # optional, Faraday logger to attach
  config.logger_options = { bodies: true } # optional, they are all valid logger_options for Faraday
end

More Details on Faraday Logger Options are here.

OR 2) Create a Client instance and pass it to the Messages, Medias or PhoneNumbers instance like this:

Without Logger:

client = WhatsappSdk::Api::Client.new("<ACCESS TOKEN>") # replace this with a valid access token
messages_api = WhatsappSdk::Api::Messages.new(client)

With Logger:

logger = Logger.new(STDOUT)
logger_options = { bodies: true }
client = WhatsappSdk::Api::Client.new("<ACCESS TOKEN>", "<API VERSION>", logger, logger_options) # replace this with a valid access token
messages_api = WhatsappSdk::Api::Messages.new(client)

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

1) Create a Meta Business app Screen Shot 2022-09-05 at 11 03 47 AM
2) Add Whatsapp to your Application Screen Shot 2022-09-05 at 11 05 43 AM
3) Add a phone number to your account Screen Shot 2022-09-05 at 11 09 22 AM

Try sending a message to your phone in the UI.

4) Copy the ACCESS_TOKEN, the SENDER_ID, the BUSINESS_ID and the RECIPIENT_NUMBER Screen Shot 2022-09-05 at 11 13 24 AM
5) Use the GEM to interact with Whatsapp

Example:

  1. Install the gem by running gem install whatsapp_sdk in the gem.
  2. Open the irb terminal by running irb
  3. require "whatsapp_sdk"
  4. Set up the ACCESS_TOKEN, the SENDER_ID, the BUSINESS_ID and the RECIPIENT_NUMBER in variables.
ACCESS_TOKEN = "EAAZAvvr0DZBs0BABRLF8zohP5Epc6pyNu"
BUSINESS_ID = 1213141516171819
SENDER_ID = 1234567891011
RECIPIENT_NUMBER = 12398765432
  1. Configure the Client by running
WhatsappSdk.configure do |config|
  config.access_token = ACCESS_TOKEN
end
  1. Try the Phone Numbers API or Messages API

Phone Numbers API

phone_numbers_api = WhatsappSdk::Api::PhoneNumbers.new
registered_number = phone_numbers_api.registered_number(SENDER_ID)

Messages API

messages_api = WhatsappSdk::Api::Messages.new
message_sent = messages_api.send_text(sender_id: SENDER_ID, recipient_number: RECIPIENT_NUMBER,
                                      message: "Hey there! it's Whatsapp Ruby SDK")

Check the example.rb file for more examples.

Operations

First, create the client and then create an instance WhatsappSdk::Api::Messages that requires a client as a param like this:

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

# Get list of templates
templates_api.templates(business_id: BUSINESS_ID)

# Create a template
new_template = templates_api.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

Business Profile API

Get the details of your business

business_profile = business_profile_api.details(123456)

Update the details of your business

business_profile_api.update(phone_number_id: SENDER_ID, params: { about: "A very cool business" } )

Phone numbers API

Get the list of phone numbers registered

phone_numbers_api.registered_numbers(123456) # accepts a business_id

Get the a phone number by id

phone_numbers_api.registered_numbers(123456) # accepts a phone_number_id

Register a phone number

phone_numbers_api.register_number(phone_number_id, pin)

Deregister a phone number

phone_numbers_api.deregister_number(phone_number_id)

Media API

Upload a media

medias_api.upload(sender_id: SENDER_ID, file_path: "tmp/whatsapp.png", type: "image/png")

Get a media

media = medias_api.media(media_id: MEDIA_ID)

Download media

medias_api.download(url: MEDIA_URL, file_path: 'tmp/downloaded_whatsapp.png', media_type: "image/png")

Delete a media

medias_api.delete(media_id: MEDIA_ID)

Messages API

Send a text message

messages_api.send_text(sender_id: 1234, recipient_number: 112345678, message: "hola")

Read a message

messages_api.read_message(sender_id: 1234, message_id: "wamid.HBgLMTM0M12345678910=")

Note: To get the message_id you can set up Webhooks 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.

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: "⛄️")

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:

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

messages_api.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.

# with a link
messages_api.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"
)

Send an audio message It could use a link or an audio_id.

# with a link
messages_api.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.

# with a link
messages_api.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.

Send a sticker message It could use a link or a sticker_id.

# with a link
messages_api.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")

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 to learn how to create contacts objects.

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:

messages_api.send_contacts(sender_id: 123123, recipient_number: 56789, contacts_json: {...})

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

Component's example
currency = WhatsappSdk::Resource::Currency.new(code: "USD", amount: 1000, fallback_value: "1000")
date_time = WhatsappSdk::Resource::DateTime.new(fallback_value: "2020-01-01T00:00:00Z")
image = WhatsappSdk::Resource::Media.new(type: "image", link: "http(s)://URL")

parameter_image = WhatsappSdk::Resource::ParameterObject.new(type: WhatsappSdk::Resource::ParameterObject::Type::Image, image: image)
# You can also use a plain string as type e.g.
# parameter_image = WhatsappSdk::Resource::ParameterObject.new(type: "image", image: image)
parameter_text = WhatsappSdk::Resource::ParameterObject.new(type: WhatsappSdk::Resource::ParameterObject::Type::Text, text: "TEXT_STRING")
parameter_currency = WhatsappSdk::Resource::ParameterObject.new(type: WhatsappSdk::Resource::ParameterObject::Type::Currency, currency: currency)
parameter_date_time = WhatsappSdk::Resource::ParameterObject.new(type: WhatsappSdk::Resource::ParameterObject::Type::DateTime, date_time: date_time)

header_component = WhatsappSdk::Resource::Component.new(
  type: WhatsappSdk::Resource::Component::Type::Header,
  parameters: [parameter_image]
)

body_component = WhatsappSdk::Resource::Component.new(
  type: WhatsappSdk::Resource::Component::Type::Body,
  parameters: [parameter_text, parameter_currency, parameter_date_time]
)

button_component1 = WhatsappSdk::Resource::Component.new(
  type: WhatsappSdk::Resource::Component::Type::Button,
  index: 0,
  sub_type: WhatsappSdk::Resource::Component::Subtype::QuickReply,
  parameters: [
    WhatsappSdk::Resource::ButtonParameter.new(type: WhatsappSdk::Resource::ButtonParameter::Type::Payload, payload: "PAYLOAD")
  ]
)

button_component2 = WhatsappSdk::Resource::Component.new(
  type: WhatsappSdk::Resource::Component::Type::Button,
  index: 1,
  sub_type: WhatsappSdk::Resource::Component::Subtype::QuickReply,
  parameters: [
    WhatsappSdk::Resource::ButtonParameter.new(type: WhatsappSdk::Resource::ButtonParameter::Type::Payload, payload: "PAYLOAD")
  ]
)
@messages_api.send_template(sender_id: 12_345, recipient_number: 12345678, name: "hello_world", language: "en_US", components_json: [component_1])

Alternatively, you could pass a plain json like this:

@messages_api.send_template(sender_id: 12_345, recipient_number: 12345678, name: "hello_world", language: "en_US", components_json: [{...}])

Send interactive messages Visit the Official API Documentation

List Message's example
interactive_header = WhatsappSdk::Resource::InteractiveHeader.new(
  type: WhatsappSdk::Resource::InteractiveHeader::Type::Text,
  text: "I am the header!"
)

interactive_body = WhatsappSdk::Resource::InteractiveBody.new(
  text: "I am the body!"
)

interactive_footer = WhatsappSdk::Resource::InteractiveFooter.new(
  text: "I am the footer!"
)

interactive_action = WhatsappSdk::Resource::InteractiveAction.new(
  type: WhatsappSdk::Resource::InteractiveAction::Type::ListMessage
)

interactive_action.button = "I am the button CTA"

interactive_section_1 = WhatsappSdk::Resource::InteractiveActionSection.new(
  title: "I am the section 1"
)
interactive_section_1_row_1 = WhatsappSdk::Resource::InteractiveActionSectionRow.new(
  title: "I am the row 1 title",
  id: "section_1_row_1",
  description: "I am the optional section 1 row 1 description"
)
interactive_section_1.add_row(interactive_section_1_row_1)
interactive_action.add_section(interactive_section_1)

interactive_list_messages = WhatsappSdk::Resource::Interactive.new(
  type: WhatsappSdk::Resource::Interactive::Type::ListMessage,
  header: interactive_header,
  body: interactive_body,
  footer: interactive_footer,
  action: interactive_action
)

messages_api.send_interactive_list_messages(
  sender_id: 12_345, recipient_number: 1234567890,
  interactive: interactive_list_messages
)

Alternatively, you could pass a plain json like this:

messages_api.send_interactive_list_messages(
  sender_id: 12_345, recipient_number: 1234567890
  interactive_json: {...}
)
Reply Button's example
interactive_header = WhatsappSdk::Resource::InteractiveHeader.new(
  type: WhatsappSdk::Resource::InteractiveHeader::Type::Text,
  text: "I am the header!"
)

interactive_body = WhatsappSdk::Resource::InteractiveBody.new(
  text: "I am the body!"
)

interactive_footer = WhatsappSdk::Resource::InteractiveFooter.new(
  text: "I am the footer!"
)

interactive_action = WhatsappSdk::Resource::InteractiveAction.new(
  type: WhatsappSdk::Resource::InteractiveAction::Type::ReplyButton
)

interactive_reply_button_1 = WhatsappSdk::Resource::InteractiveActionReplyButton.new(
  title: "I am the reply button 1",
  id: "button_1"
)
interactive_action.add_reply_button(interactive_reply_button_1)

interactive_reply_button_2 = WhatsappSdk::Resource::InteractiveActionReplyButton.new(
  title: "I am the reply button 2",
  id: "button_2"
)
interactive_action.add_reply_button(interactive_reply_button_2)

interactive_reply_buttons = WhatsappSdk::Resource::Interactive.new(
  type: WhatsappSdk::Resource::Interactive::Type::ReplyButton,
  header: interactive_header,
  body: interactive_body,
  footer: interactive_footer,
  action: interactive_action
)

messages_api.send_interactive_reply_buttons(
  sender_id: 12_345, recipient_number: 1234567890,
  interactive: interactive_reply_buttons
)

Alternative, you could pass a plain json like this:

messages_api.send_interactive_reply_buttons(
  sender_id: 12_345, recipient_number: 1234567890
  interactive_json: {...}
)

Examples

Visit the example file with examples to call the API in a single file.

Whatsapp Cloud API

Troubleshooting

If you try to send a text message directly without a message template created and approved in your Meta control panel, you can't start a chat with other people. But if you receive a message before, it's possible to send a message.

If the API response is still success, but the message is not delivered:

  • ensure the device you're sending the message to is using a supported Whatsapp version. Check documentation. Try also replying a message to the number you are registered on your Whatsapp.
  • Ensure your Meta App uses an API version greater than or equal to v.14.
  • Ensure that the Panel in the Facebook dashboard doesn't display any errors.

Note: Sometimes the messages are delayed; see Meta documentation.

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake test to run the tests.

Run ' bundle exec rake install ' to install this gem onto your local machine. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Run all the tests

  • Unit tests: Run rake test
  • Sorbet Typecheck: run srb tc
  • Linters: bundle exec rubocop

To update the Cloud API version update the version in lib/whatsapp_sdk/api/api_configuration.rb. Check the Cloud API changelog for API udpates.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/ignacio-chiazzo/ruby_whatsapp_sdk This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.

If you want a feature to be implemented in the gem, please, open an issue and we will take a look as soon as we can.

Do you want to contribute and are unsure where to start? Ping me on Twitter, and I will help you!

Check Contributing file.

License

The gem is available as open source under the terms of the MIT License.

ruby_whatsapp_sdk's People

Contributors

alienware avatar andresyebra avatar chahmedejaz avatar conr avatar dependabot[bot] avatar dvuckovic avatar emersonu avatar ignacio-chiazzo avatar mgruner avatar nbluis avatar pabloxio avatar paduszynski avatar paduszynski-sixeye avatar paulomcnally avatar renatovico avatar sahilas avatar sahilbansal17 avatar sanchezpaco avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

ruby_whatsapp_sdk's Issues

Sending a template with a dynamic URL

I created a template for WhatsApp and the template includes a button that has a dynamic URL, I'm trying to use that template to send a message, but I'm getting an error, I'm not sure what am I doing wrong here. I attached images with my code and the error I'm getting.

CleanShot 2023-12-06 at 13 49 39
CleanShot 2023-12-06 at 13 53 41

Thank you,

Zeitwerk::NameError

Describe the bug
After we try to use the gem in our production Environment (Linux Server) we faced with a error:
Zeitwerk::NameError
It just happens in Linux but when we test in a MacOS everything is working fine.

To Reproduce
Steps to reproduce the behavior:

  1. Ruby version: 2.7.1
  2. Rails 6.0.4.4
  3. ruby_whatsapp_sdk-0.5.1

Expected behavior
Start the server and send whatsapp messages through the gem

Additional context
Nothing

Implement interactive message API.

The messages_api allows users to send interactive messages.

We need to implement the functions defined in messages.rb

def send_interactive_button
# TODO: https://developers.facebook.com/docs/whatsapp/cloud-api/reference/messages#contacts-object
end
def send_interactive_reply_buttons
# TODO: https://developers.facebook.com/docs/whatsapp/cloud-api/reference/messages#contacts-object
end
def send_interactive_section
# TODO: https://developers.facebook.com/docs/whatsapp/cloud-api/reference/messages#contacts-object

Read the FB documentation here.

Add tutorial: Create a section of how to test it.

Use the example in the readme and add a tutorial on how to use it.

Example:

   Create a business account by visiting ....


   set the following variables: 
   ACCESS_TOKEN
   FROM_BUSINESS_NUMBER
   TO_PHONE_NUMBER


   # show some examples of how to use it to validate that the response is received.

We can even use this tutorial as an integration test with a real device, of course, the numbers should be opaque in the tutorial.

Add pagination to Phone Numbers API

The business_id/registered_numbers API returns an array of phone_numbers and a cursor to the next and previous page. If the set has more than 250 numbers there is no way to paginate them in the SDK. We should introduce a module that can paginate resources easily and add it to the mentioned API.

Implement Register API

Cloud API released register API.

Steps to implement it:

  • Create the methods register and deregister in the file lib/whatsapp_sdk/api/phone_numbers.rb similar to the other two methods (you need to use http POST).
  • Add a test file.

See documentation.

Add the ability to set the API version during configuration

Currently, the Whatsapp API version is hardcoded here. We should expose a way for apps to set up the API version during initialization.

For example, we could provide a config method api_version which sets the version for all API requests.

Hints

The configuration lives in configuration.rb. We could accept an api_version argument which is used across the API.

If the argument isn't passed, we'd use the hardcoded version.

Add Business API

Add Business profile API https://developers.facebook.com/docs/whatsapp/cloud-api/reference/business-profiles

TODO:
Add the new business profile API

Documentation: https://developers.facebook.com/docs/whatsapp/cloud-api/reference/business-profiles

Ho i can use sessions?

Hi, can you help me? I need to track users messages and answers, how i can use session? For example rack?
Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

Additional context
Add any other context or screenshots about the feature request here.

how to get Access Token

Hi!
Could you tell me how to get a Access Token?
Do you have some step by step for that?

config.access_token = ACCESS_TOKEN

Thank you!

Responses must return objects, never copy the attributes

Responses must return objects never copy the fields.

Context

The API returns a JSON object which is converted to a Response object.

We also have resources that model the different artifacts Whatsapp provides: Message, Media (image/video/document), component among others.

Problem

Some of the responses have implemented fields as opposed to contain resources. For example

# bad
class MessageDataResponse
  attr_accessor: URL
  attr_accessor: id

end

# good
class MessageDataResponse
  attr_accessor: message # message contains URL, id and others
end

Action items

Update the following responses:

Support jruby

Hi, I currently can't use this in jruby because it depends on oj, which is a C extension. Would you consider making oj an optional part of this gem and supporting other jruby-compatible json implementations? Thanks!

Clean up inclusions

The main module requires a few library in the main entrypoint whatsapp_sdk

require "faraday"

faraday and faraday/multipart are only required when sending http requests in the client.

TODO:

  • Remove the require file from the whatsapp_sdk module
  • Add the require file to the places needed.
  • Run all the tests and make sure they pass.
  • Grab an access token and run the example.rb file and make sure it sends the requests properly. Note: If the API says that the mssage was sent but it wasn't delivered to your phone, check the troubleshooting section.

How to Register a Phone Number

According to the documentation

phone_numbers_api.register_number(phone_number_id, pin)

Will register a Phone Number on the account.

How do I generate the PIN on the phone to be registered?

Add send reaction message

Cloud API just released a reaction API

https://developers.facebook.com/docs/whatsapp/cloud-api/guides/send-messages#reaction-messages

TODO

  • Add a new function to the messages.rb file similar to any other type of message
    sig do
    params(
    sender_id: Integer, recipient_number: Integer,
    longitude: Float, latitude: Float, name: String, address: String
    ).returns(WhatsappSdk::Api::Response)
    end
    def send_location(sender_id:, recipient_number:, longitude:, latitude:, name:, address:)
    params = {
    messaging_product: "whatsapp",
    to: recipient_number,
    recipient_type: "individual",
    type: "location",
    location: {
    longitude: longitude,
    latitude: latitude,
    name: name,
    address: address
    }
    }
    response = send_request(
    endpoint: endpoint(sender_id),
    params: params,
    headers: DEFAULT_HEADERS
    )
    WhatsappSdk::Api::Response.new(
    response: response,
    data_class_type: WhatsappSdk::Api::Responses::MessageDataResponse
    )
    end

The type should be reaction and the hptt method is post.

Error not printing

Describe the bug
Every time when i get error my code print Error: #WhatsappSdk::Api::Responses::MessageErrorResponse:0x00007fb9a00fc9e8

message_response = messages_api.send_text(
                sender_id: sender_id,
                recipient_number: from.to_i,
                message: send_message,
              )

              if message_response.ok?
                puts "Message sent to: #{message_response.data.contacts.first.input}"

                # to = message_response.data.contacts.first.input
              else
                puts "Error: #{message_response.error&.to_s}"
              end

To Reproduce
Steps to reproduce the behavior:

  1. Go to '...'

Expected behavior
A clear and concise description of what you expected to happen.

Additional context
Add any other context about the problem here.

[New Feature] Support HTTP media cache

Meta released Media HTTP caching for images. Documentation.

To implement this feature, we need to follow the next steps:

  • Add headers to the upload media endpoint
    def upload(sender_id:, file_path:, type:)
    raise FileNotFoundError, file_path unless File.file?(file_path)
    params = {
    messaging_product: "whatsapp",
    file: Faraday::FilePart.new(file_path, type),
    type: type
    }
    response = send_request(http_method: "post", endpoint: "#{sender_id}/media", params: params)
    WhatsappSdk::Api::Response.new(
    response: response,
    data_class_type: WhatsappSdk::Api::Responses::MediaDataResponse
    )
    end
  • Add tests to the media test file

Allow for a logger to be attached to client

I am exploring the whatapp api with this great gem.

As I'm new to the whatsapp api, I do a lot of stupid mistakes. I have a hard time debbugging the mistakes I do because there no way to attach a logger to Faraday to see the HTTP requests (with headers and bodies).

It would be nice if while configuring the client one could set a logger:

# config/initializers/whatsapp_sdk.rb
WhatsappSdk.configure do |config|
  config.access_token = ACCESS_TOKEN
  config.logger = Rails.logger
end

Support Image/webp

Describe the bug
When receive a image/webp (sticker eg) the download medias doesn't work

To Reproduce

  1. Send a sticker image
  2. Try download :)

Expected behavior
Download happened

Additional context

I Made a ugly monkey patch

WhatsappSdk::Resource::MediaTypes::IMAGE_TYPES = WhatsappSdk::Resource::MediaTypes::IMAGE_TYPES.dup
WhatsappSdk::Resource::MediaTypes::IMAGE_TYPES.push("image/webp")
WhatsappSdk::Resource::MediaTypes::IMAGE_TYPES.freeze


WhatsappSdk::Resource::MediaTypes::SUPPORTED_MEDIA_TYPES = WhatsappSdk::Resource::MediaTypes::SUPPORTED_MEDIA_TYPES.dup
WhatsappSdk::Resource::MediaTypes::SUPPORTED_MEDIA_TYPES.push("image/webp")
WhatsappSdk::Resource::MediaTypes::SUPPORTED_MEDIA_TYPES.freeze

and all worked :)

How to send messages Production Environment?

Describe the bug
After to finish all configuration and added the new phone number, when i try to send a message using the Gem, I receive the message "message sent" but the recipient dont receive any message.

To Reproduce
Steps to reproduce the behavior:
the Code below:
def send_whatsapp_message
@config = Config.first
require 'whatsapp_sdk'

#variables
access_token = @config.access_token_whats
business_id = @config.business_id_whats
sender_id = @config.sender_id_whats
recipient_number = params[:numero_whatsapp]

client = WhatsappSdk::Api::Client.new(access_token) # replace this with a valid access token
messages_api = WhatsappSdk::Api::Messages.new(client)

message_sent = messages_api.send_text(sender_id: sender_id.to_i, recipient_number: recipient_number.to_i, message: params[:mensagem].to_s)
print_message_sent(message_sent)
redirect_back(fallback_location: root_path)
end

def print_message_sent(message_response)
if message_response.ok?
sweetalert_success("Mensagem enviada com sucesso para: #{message_response.data.contacts.first.input}", 'Sucesso!', persistent: 'Ok')
puts "Message sent to: #{message_response.data.inspect}"
else
sweetalert_success("Ocorreu um erro: #{message_response.error&.to_s}", 'Erro:', persistent: 'Ok')
end
end

THIS IS MY RESPONSE:
Message sent to: #<WhatsappSdk::Api::Responses::MessageDataResponse:0x000000010667d728 @contacts=[#<WhatsappSdk::Resource::ContactResponse:0x000000010667d570 @input="5511991078572", @wa_id="5511991078572">], @messages=[#<WhatsappSdk::Resource::Message:0x000000010667d368 @id="wamid.HBgNNTUxMTk5MTA3ODU3MhUCABEYEjBFQkI2OEYyNTdBMTBDRUY1NwA=">], @raw_data_response={"messaging_product"=>"whatsapp", "contacts"=>[{"input"=>"5511991078572", "wa_id"=>"5511991078572"}], "messages"=>[{"id"=>"wamid.HBgNNTUxMTk5MTA3ODU3MhUCABEYEjBFQkI2OEYyNTdBMTBDRUY1NwA="}]}>

Expected behavior
The recipient receive the message.

If you look to my configs at images attached you can see that everything is configured, (I guess)
There is something else more to do?
thanks!

Additional context
Add any other context about the problem here
Captura de Tela 2023-11-28 às 16 36 53
Captura de Tela 2023-11-28 às 16 37 18
Captura de Tela 2023-11-28 às 16 38 39
.

Use RBS type annotations instead of Sorbet

Sorbet is nice, but it's a pain to make everyone install it in production apps since it's not widely used and is not part of Ruby core.

Instead, Sorbet should be a development_dependency, and this gem should use *.rbs files to annotate types which are the Ruby-core way and can be read by Sorbet. The Ruby .rb files should be kept clean of Sorbet markup.

I think this is a best practice for gem maintainers.

Please let me know if you'd accept a PR for this.

Add a singleton that handles the session.

Instead of passing the token everywhere, we can have a singleton that stores the token and is used in every client call.

Example:

#before
client = WhatsappSdk::Api::Client.new("<ACCESS TOKEN>")
messages_api = WhatsappSdk::Api::Messages.new(client)
phone_numbers_api = WhatsappSdk::Api::PhoneNumbers.new(client)
phone_numbers_api.registered_numbers("123456")

# after
### we can have an initializer that stores the access token
WhatsappSdk::Api::Client.setup do |client|
  client.access_token = "<ACCESS TOKEN>"
end

WhatsappSdk::Api::PhoneNumbers.registered_numbers("123456")

`rails zeitwerk:check` crashes

Describe the bug
We use this gem in our Rails application, thank you so much for providing it!

While the regular rails stack still seems to work fine, the zeitwerk:check rake task that we use for linting in CI fails now:

$ rails r 'pp true'
true

$ rails zeitwerk:check
Hold on, I am eager loading the application.
rails aborted!
Errno::ENOENT: No such file or directory @ rb_check_realpath_internal - config/api_versions.yml (Errno::ENOENT)

Tasks: TOP => zeitwerk:check
(See full trace by running task with --trace)

To Reproduce
Steps to reproduce the behavior:

  1. Run rails zeitwerk:check in your rails app.

Expected behavior
No error should occur.

Additional context

It seems that the recent changes from #126 introduced a regression.

Could it be an alternative to switch from loading a yaml file to preparing the list directly in a ruby file?

Regarding refreshing the access token

Hello,

So it seems the access token provided by Facebook is temporary and it needs to be refreshed each day I think, is that implemented inside the gem, or do I need to handle that from my end?

Thank you,

Groups

Hi, from what I saw the SDK doesn't support group management, I'll put some things here to understand how the groups API works

  • Create Group
  • Update group info
  • Send message in group
  • Remove group participant

Add yardoc

Add yardoc to the public functions so that consumers can use it easily.

Read a message, and how to get the id and other data

Discussed in #92

Originally posted by AlkhabazHasan July 18, 2023
Grate gem and well documented and, it save times of works, but isn't messages_api.read_message(sender_id: 1234, message_id: "wamid.HBgLMTM0M12345678910=") needs more explanation?

It is so easy to get the id for sent message:

message_sent = messages_api.send_text(sender_id: sender, recipient_number: phone_numbers, message: "Hey there! it's Whatsapp Ruby SDK")
message_id = message_sent.data.messages.first.id
puts message_id

But for messages_api.read_message I have to do it like this:
params["entry"][0]["changes"][0]["value"]["messages"][0]["id"]

Is there something I didn't get?
I think I may need some help!

Send Message as a Reply

Is your feature request related to a problem? Please describe.
I'm working on a use-case that involves replying to users' messages with context, i.e., against an existing conversation, shown as below.
WA Reply

Additional context
Documentation
Enabling this would require to pass context object with the request params, which will have the message_id for the user message. Replies seem to be supported for text, audio, document, video, location, sticker and contact.

Please let me know how I can help out here in case you wish to incorporate the support in this helpful library.

Support File Upload Resumable Interface - Change Profile Picture

Is your feature request related to a problem? Please describe.

For change Profile Picture, sic, the upload of image works different of rest the cloud sdk api, it's based on resumable interface.

Specification for profile_picture_handle field in:
https://developers.facebook.com/docs/whatsapp/cloud-api/reference/business-profiles/

Resumable Interface Upload:
https://developers.facebook.com/docs/graph-api/guides/upload

Additional context
I Tried use Koala gem, but only helped for call the graph api, does not have support for resumable upload too

Can we send message with multiple phone numbers?

Hi, I have following issue, pls take a look

Base on my research, Whatsapp let us add maximum 2 phone numbers to an Whatsapp business account.
So now if I have an system with multiple users register as a business (ex: user1 is owner of flower company, user2 is owner of food company...) and I want to integrate Whatsapp API (send messages, reply, get messages...) for each their customers. The whole system with a lot of 'business users' (user1, user2...) will be use same phone numbers as registered to Whatsapp developer app before when they send messages to their customers, right ? So when customer receive messages, they will see same name of business with same phone number.

Can we use each phone number of users when they registered to system when send messages through Whatsapp ?

Use major version compatible dependencies

I believe this is a little detail but it would be better if the dependencies defined in the gemspec did not fix minor or patch versions, otherwise projects that include this gem will never be able to update these dependencies without a release even if they are compatible (semver)

Additional context
An example of this is now occurring with Faraday.

Gemspec

spec.add_dependency("faraday", "~> 2.7.10")

The last Faraday version is v2.7.11 and theres no breaking changes.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.