156 lines
5.2 KiB
Ruby
156 lines
5.2 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'json'
|
|
require 'net/http'
|
|
require 'net/https'
|
|
require 'uri'
|
|
|
|
# Direct Signal CLI API client for communicating with signal-cli-rest-api
|
|
# All Signal operations go through this single class
|
|
class CdrSignalApi
|
|
def initialize(base_url = nil)
|
|
@base_url = base_url || ENV.fetch('SIGNAL_CLI_URL', 'http://signal-cli-rest-api:8080')
|
|
end
|
|
|
|
# Fetch pending messages for a phone number
|
|
# GET /v1/receive/{number}
|
|
def fetch_messages(phone_number)
|
|
url = "#{@base_url}/v1/receive/#{CGI.escape(phone_number)}"
|
|
response = Faraday.get(url, nil, { 'Accept' => 'application/json' })
|
|
return [] unless response.success?
|
|
|
|
JSON.parse(response.body)
|
|
rescue JSON::ParserError, Faraday::Error => e
|
|
Rails.logger.error "CdrSignalApi: Failed to fetch messages for #{phone_number}: #{e.message}"
|
|
[]
|
|
end
|
|
|
|
# Fetch an attachment by ID
|
|
# GET /v1/attachments/{id}
|
|
def fetch_attachment(attachment_id)
|
|
url = "#{@base_url}/v1/attachments/#{CGI.escape(attachment_id)}"
|
|
response = Faraday.get(url)
|
|
return nil unless response.success?
|
|
|
|
response.body
|
|
rescue Faraday::Error => e
|
|
Rails.logger.error "CdrSignalApi: Failed to fetch attachment #{attachment_id}: #{e.message}"
|
|
nil
|
|
end
|
|
|
|
# List all groups for a phone number
|
|
# GET /v1/groups/{number}
|
|
def list_groups(phone_number)
|
|
url = "#{@base_url}/v1/groups/#{CGI.escape(phone_number)}"
|
|
response = Faraday.get(url, nil, { 'Accept' => 'application/json' })
|
|
return [] unless response.success?
|
|
|
|
JSON.parse(response.body)
|
|
rescue JSON::ParserError, Faraday::Error => e
|
|
Rails.logger.error "CdrSignalApi: Failed to list groups for #{phone_number}: #{e.message}"
|
|
[]
|
|
end
|
|
|
|
# Check if a phone number is registered with signal-cli
|
|
# GET /v1/about
|
|
def check_number(phone_number)
|
|
# Verify we can connect to signal-cli-rest-api
|
|
url = "#{@base_url}/v1/about"
|
|
response = Faraday.get(url, nil, { 'Accept' => 'application/json' })
|
|
return false unless response.success?
|
|
|
|
# Try to list groups for this number to verify it's registered
|
|
groups_url = "#{@base_url}/v1/groups/#{CGI.escape(phone_number)}"
|
|
groups_response = Faraday.get(groups_url, nil, { 'Accept' => 'application/json' })
|
|
groups_response.success?
|
|
rescue Faraday::Error => e
|
|
Rails.logger.error "CdrSignalApi: Failed to check number #{phone_number}: #{e.message}"
|
|
false
|
|
end
|
|
|
|
# Send a message via Signal CLI
|
|
# POST /v2/send
|
|
def send_message(from_number, recipients, message, options = {})
|
|
url = "#{@base_url}/v2/send"
|
|
|
|
data = {
|
|
number: from_number,
|
|
recipients: Array(recipients),
|
|
message: message
|
|
}
|
|
|
|
# Add base64 attachments if provided
|
|
if options[:attachments].present?
|
|
data[:base64Attachments] = options[:attachments].map { |a| a[:data] }
|
|
end
|
|
|
|
# Add quote parameters if provided
|
|
if options[:quote_timestamp] && options[:quote_author] && options[:quote_message]
|
|
data[:quoteTimestamp] = options[:quote_timestamp]
|
|
data[:quoteAuthor] = options[:quote_author]
|
|
data[:quoteMessage] = options[:quote_message]
|
|
end
|
|
|
|
response = Faraday.post(url, data.to_json, {
|
|
'Content-Type' => 'application/json',
|
|
'Accept' => 'application/json'
|
|
})
|
|
|
|
unless response.success?
|
|
Rails.logger.error "CdrSignalApi: Failed to send message: #{response.status} #{response.body}"
|
|
raise "Failed to send Signal message: #{response.status}"
|
|
end
|
|
|
|
JSON.parse(response.body)
|
|
rescue Faraday::Error => e
|
|
Rails.logger.error "CdrSignalApi: Failed to send message: #{e.message}"
|
|
raise "Failed to send Signal message: #{e.message}"
|
|
end
|
|
|
|
# Create a new Signal group
|
|
# POST /v1/groups/{number}
|
|
def create_group(phone_number, name:, members:, description: nil)
|
|
url = "#{@base_url}/v1/groups/#{CGI.escape(phone_number)}"
|
|
|
|
data = {
|
|
name: name,
|
|
members: Array(members),
|
|
description: description
|
|
}.compact
|
|
|
|
response = Faraday.post(url, data.to_json, {
|
|
'Content-Type' => 'application/json',
|
|
'Accept' => 'application/json'
|
|
})
|
|
|
|
unless response.success?
|
|
Rails.logger.error "CdrSignalApi: Failed to create group: #{response.status} #{response.body}"
|
|
raise "Failed to create Signal group: #{response.status}"
|
|
end
|
|
|
|
JSON.parse(response.body)
|
|
rescue Faraday::Error => e
|
|
Rails.logger.error "CdrSignalApi: Failed to create group: #{e.message}"
|
|
raise "Failed to create Signal group: #{e.message}"
|
|
end
|
|
|
|
# Update a Signal group
|
|
# PUT /v1/groups/{number}/{groupId}
|
|
def update_group(phone_number, group_id, name: nil, description: nil)
|
|
url = "#{@base_url}/v1/groups/#{CGI.escape(phone_number)}/#{CGI.escape(group_id)}"
|
|
|
|
data = {}
|
|
data[:name] = name if name.present?
|
|
data[:description] = description if description.present?
|
|
|
|
response = Faraday.put(url, data.to_json, {
|
|
'Content-Type' => 'application/json',
|
|
'Accept' => 'application/json'
|
|
})
|
|
|
|
response.success?
|
|
rescue Faraday::Error => e
|
|
Rails.logger.error "CdrSignalApi: Failed to update group: #{e.message}"
|
|
false
|
|
end
|
|
end
|