iachat/app/controllers/api/v1/accounts/inboxes/wuzapi_controller.rb
2026-02-26 10:49:00 -03:00

144 lines
4.8 KiB
Ruby

class Api::V1::Accounts::Inboxes::WuzapiController < Api::V1::Accounts::BaseController
before_action :fetch_inbox
before_action :ensure_wuzapi_provider
def show
# Session Status
status_data = client.session_status(user_token)
# Wuzapi returns nested data: { data: { connected: true, jid: "..." } }
# Pass it through to frontend for validation
render json: status_data
rescue Wuzapi::Client::Error => e
Rails.logger.error "Wuzapi Status Error: #{e.message}"
render json: { error: e.message }, status: :unprocessable_entity
rescue StandardError => e
Rails.logger.error "Wuzapi Status Critical Error: #{e.message}"
render json: { error: e.message }, status: :internal_server_error
end
def qr
# Get QR Code
# Check status first to avoid error if already connected
status_data = client.session_status(user_token)
# Wuzapi status can be string or object with 'status'/'state'
status = status_data['status'] || status_data['state'] || status_data
Rails.logger.info "Wuzapi Connect/QR Flow - Current Status: #{status}"
return if already_connected?(status)
qr_data = client.get_qr_code(user_token)
log_qr_data_keys(qr_data)
render json: qr_data
rescue Wuzapi::Client::Error => e
Rails.logger.error "Wuzapi QR Error: #{e.message}"
render json: { error: e.message }, status: :unprocessable_entity
rescue StandardError => e
Rails.logger.error "Wuzapi QR Critical Error: #{e.message}"
render json: { error: e.message }, status: :internal_server_error
end
def connect
# Trigger connection (if needed by Wuzapi flow)
ensure_webhook_is_configured
result = client.session_connect(user_token)
render json: result
rescue Wuzapi::Client::Error => e
# Idempotency: "already connected" is a success state
if e.message.include?('already connected')
render json: { success: true, message: 'Already connected' }, status: :ok
else
Rails.logger.error "Wuzapi Connect Error: #{e.message}"
render json: { error: e.message }, status: :unprocessable_entity
end
rescue StandardError => e
Rails.logger.error "Wuzapi Connect Critical Error: #{e.message}"
render json: { error: e.message }, status: :internal_server_error
end
def disconnect
# Disconnect session
result = client.session_logout(user_token) || client.session_disconnect(user_token)
render json: result
rescue Wuzapi::Client::Error => e
render json: { error: e.message }, status: :unprocessable_entity
rescue StandardError => e
render json: { error: e.message }, status: :internal_server_error
end
def webhook_info
info = client.get_webhook(user_token)
render json: info
rescue Wuzapi::Client::Error => e
render json: { error: e.message }, status: :unprocessable_entity
rescue StandardError => e
render json: { error: e.message }, status: :internal_server_error
end
def update_webhook
# Re-calculate correct webhook URL from model
url = expected_webhook_url
client.update_webhook(user_token, url)
render json: { success: true, message: 'Webhook updated successfully', webhook_url: url }
rescue Wuzapi::Client::Error => e
render json: { error: e.message }, status: :unprocessable_entity
rescue StandardError => e
render json: { error: e.message }, status: :internal_server_error
end
private
def fetch_inbox
@inbox = Current.account.inboxes.find(params[:inbox_id])
end
def ensure_wuzapi_provider
return if @inbox.channel.provider == 'wuzapi'
render json: { error: 'Not a Wuzapi inbox' }, status: :bad_request
end
def client
@client ||= Wuzapi::Client.new(@inbox.channel.provider_config['wuzapi_base_url'])
end
def user_token
token = @inbox.channel.wuzapi_user_token
if token.blank?
Rails.logger.error "Wuzapi Token Missing for Inbox #{@inbox.id}"
raise 'Token Wuzapi ausente; reprovisionar usuário'
else
Rails.logger.info "Wuzapi Request using Token (last 6): ******#{token.to_s[-6..]}"
end
token
end
def ensure_webhook_is_configured
client.set_webhook(user_token, expected_webhook_url)
rescue Wuzapi::Client::Error => e
Rails.logger.warn "Wuzapi webhook pre-connect setup failed for inbox #{@inbox.id}: #{e.message}"
end
def expected_webhook_url
@expected_webhook_url ||= @inbox.callback_webhook_url.to_s.sub('/webhooks/whatsapp/+', '/webhooks/whatsapp/')
end
def already_connected?(status)
if %w[CONNECTED inChat success].include?(status)
Rails.logger.info 'Wuzapi is already connected. Skipping QR.'
render json: { qrcode: nil, status: 'CONNECTED', message: 'Already connected' }
true
else
false
end
end
def log_qr_data_keys(qr_data)
Rails.logger.info "Wuzapi QR Data Response keys: #{qr_data.keys}"
rescue StandardError
Rails.logger.info 'Wuzapi QR Data Response keys: nil'
end
end