Class: Whatsapp::Client
- Inherits:
-
Object
- Object
- Whatsapp::Client
- Defined in:
- lib/whatsapp/client.rb
Overview
Main interface for interacting with a WhatsApp account.
Manages the bridge lifecycle, sends messages, and dispatches events. Each Client instance owns one bridge process and one WhatsApp session.
Instance Attribute Summary collapse
-
#bridge ⇒ Bridge?
readonly
The bridge communication layer.
-
#events ⇒ Events
readonly
Event emitter for this client.
-
#rate_limiter ⇒ RateLimiter
readonly
Rate limiter instance.
Instance Method Summary collapse
-
#add_group_participants(group_id, participants:) ⇒ Hash
Add participants to a group.
-
#business_profile(phone) ⇒ Hash
Get a contact's business profile.
-
#connect ⇒ self
Start the bridge and connect to WhatsApp.
-
#connected? ⇒ Boolean
Whether this client is connected to WhatsApp.
-
#create_group(subject:, participants:) ⇒ Group
Create a new group.
-
#disconnect ⇒ void
Disconnect from WhatsApp and stop the bridge.
-
#fetch_status(phone) ⇒ Hash
Get a contact's status/about text.
-
#group(group_id) ⇒ Group
Get detailed info about a group.
-
#groups ⇒ Array<Group>
List all groups the account participates in.
-
#initialize(config: Whatsapp.configuration) ⇒ Client
constructor
A new instance of Client.
-
#on(event_name) {|data| ... } ⇒ void
Register a handler for any event.
-
#on_connected {|data| ... } ⇒ void
Register a handler for successful connection.
-
#on_contacts_update {|contacts| ... } ⇒ void
Register a handler for contact list updates.
-
#on_message {|message| ... } ⇒ void
Register a handler for new (live) incoming messages.
-
#on_message_any {|message| ... } ⇒ void
Register a handler for all messages (live + history sync).
-
#on_message_delivered {|data| ... } ⇒ void
Register a handler for "delivered" status only.
-
#on_message_read {|data| ... } ⇒ void
Register a handler for "read" status only.
-
#on_message_receipt {|data| ... } ⇒ void
Register a handler for message receipt updates.
-
#on_message_sent {|data| ... } ⇒ void
Register a handler for "sent" status only.
-
#on_message_status {|data| ... } ⇒ void
Register a handler for all message status changes.
-
#on_poll_vote {|data| ... } ⇒ void
Register a handler for poll vote results.
-
#on_presence_update {|data| ... } ⇒ void
Register a handler for presence updates.
-
#on_qr {|qr| ... } ⇒ void
Register a handler for QR code events.
-
#on_whatsapp?(phone) ⇒ Hash
Check if a phone number is registered on WhatsApp.
-
#profile_picture(phone, high_res: false) ⇒ Hash
Get a contact's profile picture URL.
-
#rate_limit_stats ⇒ Hash
Get rate limiting statistics.
-
#read_messages(keys) ⇒ Hash
Mark messages as read.
-
#remove_group_participants(group_id, participants:) ⇒ Hash
Remove participants from a group.
-
#safety_status ⇒ Hash
Get comprehensive safety status for monitoring.
-
#send_message(to:, text: nil, media: nil, location: nil, contact: nil, react: nil, poll: nil, quoted_message_id: nil, unsafe: false) ⇒ Message
Send a message to a WhatsApp recipient.
-
#send_presence(type, to: nil) ⇒ Hash
Send a presence update.
-
#status ⇒ Hash
Get the bridge and WhatsApp connection status.
-
#subscribe_presence(jid) ⇒ Hash
Subscribe to presence updates for a JID.
-
#update_group(group_id, subject: nil, description: nil) ⇒ Hash
Update a group's subject and/or description.
Constructor Details
#initialize(config: Whatsapp.configuration) ⇒ Client
Returns a new instance of Client.
25 26 27 28 29 30 31 32 |
# File 'lib/whatsapp/client.rb', line 25 def initialize(config: Whatsapp.configuration) @config = config @connection = Connection.new(config) @bridge = nil @events = Events.new @rate_limiter = RateLimiter.new(config) @connected = false end |
Instance Attribute Details
#bridge ⇒ Bridge? (readonly)
Returns the bridge communication layer.
22 23 24 |
# File 'lib/whatsapp/client.rb', line 22 def bridge @bridge end |
#events ⇒ Events (readonly)
Returns event emitter for this client.
16 17 18 |
# File 'lib/whatsapp/client.rb', line 16 def events @events end |
#rate_limiter ⇒ RateLimiter (readonly)
Returns rate limiter instance.
19 20 21 |
# File 'lib/whatsapp/client.rb', line 19 def rate_limiter @rate_limiter end |
Instance Method Details
#add_group_participants(group_id, participants:) ⇒ Hash
Add participants to a group.
366 367 368 369 |
# File 'lib/whatsapp/client.rb', line 366 def add_group_participants(group_id, participants:) ensure_bridge! @bridge.post("/groups/#{group_id}/participants", {action: "add", participants: participants}) end |
#business_profile(phone) ⇒ Hash
Get a contact's business profile.
296 297 298 299 |
# File 'lib/whatsapp/client.rb', line 296 def business_profile(phone) ensure_bridge! @bridge.post("/contacts/business-profile", {jid: normalize_number(phone)}) end |
#connect ⇒ self
Start the bridge and connect to WhatsApp.
37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/whatsapp/client.rb', line 37 def connect Whatsapp.logger.info "Starting bridge..." @connection.start! @bridge = Bridge.new(@connection, config: @config) @bridge.open_websocket! @bridge.on_event do |event, data| handle_event(event, data) end Whatsapp.logger.info "Bridge started, waiting for WhatsApp connection" self end |
#connected? ⇒ Boolean
Whether this client is connected to WhatsApp.
64 65 66 |
# File 'lib/whatsapp/client.rb', line 64 def connected? @connected end |
#create_group(subject:, participants:) ⇒ Group
Create a new group.
339 340 341 342 343 |
# File 'lib/whatsapp/client.rb', line 339 def create_group(subject:, participants:) ensure_bridge! response = @bridge.post("/groups", {subject: subject, participants: participants}) Group.new(response[:group]) end |
#disconnect ⇒ void
This method returns an undefined value.
Disconnect from WhatsApp and stop the bridge.
54 55 56 57 58 59 |
# File 'lib/whatsapp/client.rb', line 54 def disconnect Whatsapp.logger.info "Disconnecting..." @bridge&.close! @connection.stop! @connected = false end |
#fetch_status(phone) ⇒ Hash
Get a contact's status/about text.
286 287 288 289 |
# File 'lib/whatsapp/client.rb', line 286 def fetch_status(phone) ensure_bridge! @bridge.post("/contacts/status", {jid: normalize_number(phone)}) end |
#group(group_id) ⇒ Group
Get detailed info about a group.
327 328 329 330 331 |
# File 'lib/whatsapp/client.rb', line 327 def group(group_id) ensure_bridge! response = @bridge.get("/groups/#{group_id}") Group.new(response[:group]) end |
#groups ⇒ Array<Group>
List all groups the account participates in.
316 317 318 319 320 |
# File 'lib/whatsapp/client.rb', line 316 def groups ensure_bridge! response = @bridge.get("/groups") Array(response[:groups]).map { |g| Group.new(g) } end |
#on(event_name) {|data| ... } ⇒ void
This method returns an undefined value.
Register a handler for any event.
116 117 118 |
# File 'lib/whatsapp/client.rb', line 116 def on(event_name, &block) events.on(event_name, &block) end |
#on_connected {|data| ... } ⇒ void
This method returns an undefined value.
Register a handler for successful connection.
151 152 153 |
# File 'lib/whatsapp/client.rb', line 151 def on_connected(&block) on("connected", &block) end |
#on_contacts_update {|contacts| ... } ⇒ void
This method returns an undefined value.
Register a handler for contact list updates.
306 307 308 |
# File 'lib/whatsapp/client.rb', line 306 def on_contacts_update(&block) on("contacts.update", &block) end |
#on_message {|message| ... } ⇒ void
This method returns an undefined value.
Register a handler for new (live) incoming messages.
134 135 136 |
# File 'lib/whatsapp/client.rb', line 134 def (&block) on("message.new") { |data| block.call(Message.new(data)) } end |
#on_message_any {|message| ... } ⇒ void
This method returns an undefined value.
Register a handler for all messages (live + history sync).
143 144 145 |
# File 'lib/whatsapp/client.rb', line 143 def (&block) on("message") { |data| block.call(Message.new(data)) } end |
#on_message_delivered {|data| ... } ⇒ void
This method returns an undefined value.
Register a handler for "delivered" status only.
|
|
# File 'lib/whatsapp/client.rb', line 170
|
#on_message_read {|data| ... } ⇒ void
This method returns an undefined value.
Register a handler for "read" status only.
182 183 184 185 186 |
# File 'lib/whatsapp/client.rb', line 182 {on_message_sent: "sent", on_message_delivered: "delivered", on_message_read: "read"}.each do |method_name, status| define_method(method_name) do |&block| on("message.status") { |data| block.call(data) if data[:status] == status } end end |
#on_message_receipt {|data| ... } ⇒ void
This method returns an undefined value.
Register a handler for message receipt updates.
245 246 247 |
# File 'lib/whatsapp/client.rb', line 245 def (&block) on("message-receipt.update", &block) end |
#on_message_sent {|data| ... } ⇒ void
This method returns an undefined value.
Register a handler for "sent" status only.
|
|
# File 'lib/whatsapp/client.rb', line 164
|
#on_message_status {|data| ... } ⇒ void
This method returns an undefined value.
Register a handler for all message status changes.
160 161 162 |
# File 'lib/whatsapp/client.rb', line 160 def (&block) on("message.status", &block) end |
#on_poll_vote {|data| ... } ⇒ void
This method returns an undefined value.
Register a handler for poll vote results.
254 255 256 |
# File 'lib/whatsapp/client.rb', line 254 def on_poll_vote(&block) on("poll.vote", &block) end |
#on_presence_update {|data| ... } ⇒ void
This method returns an undefined value.
Register a handler for presence updates.
236 237 238 |
# File 'lib/whatsapp/client.rb', line 236 def on_presence_update(&block) on("presence.update", &block) end |
#on_qr {|qr| ... } ⇒ void
This method returns an undefined value.
Register a handler for QR code events.
125 126 127 |
# File 'lib/whatsapp/client.rb', line 125 def on_qr(&block) on("qr") { |data| block.call(data[:qr]) } end |
#on_whatsapp?(phone) ⇒ Hash
Check if a phone number is registered on WhatsApp.
265 266 267 268 |
# File 'lib/whatsapp/client.rb', line 265 def on_whatsapp?(phone) ensure_bridge! @bridge.post("/contacts/check", {phone: normalize_number(phone)}) end |
#profile_picture(phone, high_res: false) ⇒ Hash
Get a contact's profile picture URL.
276 277 278 279 |
# File 'lib/whatsapp/client.rb', line 276 def profile_picture(phone, high_res: false) ensure_bridge! @bridge.post("/contacts/profile-picture", {jid: normalize_number(phone), high_res: high_res}) end |
#rate_limit_stats ⇒ Hash
Get rate limiting statistics.
396 397 398 |
# File 'lib/whatsapp/client.rb', line 396 def rate_limit_stats @rate_limiter.stats end |
#read_messages(keys) ⇒ Hash
Mark messages as read.
220 221 222 223 224 225 226 227 228 229 |
# File 'lib/whatsapp/client.rb', line 220 def (keys) ensure_bridge! camel_keys = Array(keys).map do |key| h = {remoteJid: key[:remote_jid] || key[:remoteJid], id: key[:id]} participant = key[:participant] h[:participant] = participant if participant h end @bridge.post("/messages/read", {keys: camel_keys}) end |
#remove_group_participants(group_id, participants:) ⇒ Hash
Remove participants from a group.
377 378 379 380 |
# File 'lib/whatsapp/client.rb', line 377 def remove_group_participants(group_id, participants:) ensure_bridge! @bridge.post("/groups/#{group_id}/participants", {action: "remove", participants: participants}) end |
#safety_status ⇒ Hash
Get comprehensive safety status for monitoring.
423 424 425 |
# File 'lib/whatsapp/client.rb', line 423 def safety_status @rate_limiter.safety_status end |
#send_message(to:, text: nil, media: nil, location: nil, contact: nil, react: nil, poll: nil, quoted_message_id: nil, unsafe: false) ⇒ Message
Send a message to a WhatsApp recipient.
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/whatsapp/client.rb', line 83 def (to:, text: nil, media: nil, location: nil, contact: nil, react: nil, poll: nil, quoted_message_id: nil, unsafe: false) ensure_bridge! recipient = normalize_number(to) if @config.rate_limiting_enabled && !unsafe @rate_limiter.acquire!(recipient) Whatsapp.logger.debug "Rate limiter OK", to: recipient end # Typing simulation: send "composing" presence before text messages if @config.typing_simulation && text && !react && !unsafe simulate_typing(recipient, text) end Whatsapp.logger.info "Sending message", to: recipient body = { to: recipient, text: text, media: media, location: location, contact: contact, react: react, poll: poll, quoted_message_id: } response = @bridge.post("/messages/send", body) msg = Message.new(response[:message] || response) Whatsapp.logger.info "Message sent", id: msg.id, to: recipient msg end |
#send_presence(type, to: nil) ⇒ Hash
Send a presence update.
196 197 198 199 200 201 |
# File 'lib/whatsapp/client.rb', line 196 def send_presence(type, to: nil) ensure_bridge! body = {type: type} body[:to] = normalize_number(to) if to @bridge.post("/presence/update", body) end |
#status ⇒ Hash
Get the bridge and WhatsApp connection status.
388 389 390 391 |
# File 'lib/whatsapp/client.rb', line 388 def status ensure_bridge! @bridge.status end |
#subscribe_presence(jid) ⇒ Hash
Subscribe to presence updates for a JID.
208 209 210 211 |
# File 'lib/whatsapp/client.rb', line 208 def subscribe_presence(jid) ensure_bridge! @bridge.post("/presence/subscribe", {jid: normalize_number(jid)}) end |
#update_group(group_id, subject: nil, description: nil) ⇒ Hash
Update a group's subject and/or description.
352 353 354 355 356 357 358 |
# File 'lib/whatsapp/client.rb', line 352 def update_group(group_id, subject: nil, description: nil) ensure_bridge! body = {} body[:subject] = subject if subject body[:description] = description unless description.nil? @bridge.put("/groups/#{group_id}", body) end |