mirror of
https://github.com/chatwoot/chatwoot.git
synced 2026-06-04 21:02:35 +08:00
Some checks failed
Frontend Lint & Test / test (push) Has been cancelled
Publish Chatwoot EE docker images / build (linux/amd64, ubuntu-latest) (push) Has been cancelled
Publish Chatwoot EE docker images / build (linux/arm64, ubuntu-22.04-arm) (push) Has been cancelled
Publish Chatwoot CE docker images / build (linux/amd64, ubuntu-latest) (push) Has been cancelled
Publish Chatwoot CE docker images / build (linux/arm64, ubuntu-22.04-arm) (push) Has been cancelled
Run Chatwoot CE spec / lint-backend (push) Has been cancelled
Run Chatwoot CE spec / lint-frontend (push) Has been cancelled
Run Chatwoot CE spec / frontend-tests (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (0, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (1, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (10, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (11, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (12, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (13, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (14, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (15, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (2, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (3, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (4, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (5, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (6, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (7, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (8, 16) (push) Has been cancelled
Run Chatwoot CE spec / backend-tests (9, 16) (push) Has been cancelled
Publish Chatwoot EE docker images / merge (push) Has been cancelled
Publish Chatwoot CE docker images / merge (push) Has been cancelled
We're getting many customer reports saying "I'm not getting notifications." We can't always identify the root cause since there are multiple points of failure. Added a **Push Diagnostics** tool in Super Admin to help us investigate mobile/web push issues. Here's how it works: - Look up a user by email/ID → see all their registered subscriptions with device info (iOS/Android, brand, model), token freshness, and last-updated time - Send a customizable test push and read the raw FCM/web-push/relay response to see if the customer is receiving push notifications—if not, it will show proper errors. - Delete broken subscriptions so the mobile app re-registers on next launch <img width="3816" height="1974" alt="CleanShot 2026-04-20 at 12 56 56@2x" src="https://github.com/user-attachments/assets/08ecab6f-7ec3-44b3-a114-5e6eb8cf0879" /> Fixes https://linear.app/chatwoot/issue/CW-6892/push-diagnostics-tool --------- Co-authored-by: Muhsin <12408980+muhsin-k@users.noreply.github.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
134 lines
4.2 KiB
Ruby
134 lines
4.2 KiB
Ruby
# TODO: lets use HTTParty instead of RestClient
|
|
class ChatwootHub
|
|
DEFAULT_BASE_URL = 'https://hub.2.chatwoot.com'.freeze
|
|
|
|
def self.base_url
|
|
DEFAULT_BASE_URL
|
|
end
|
|
|
|
def self.ping_url
|
|
"#{base_url}/ping"
|
|
end
|
|
|
|
def self.registration_url
|
|
"#{base_url}/instances"
|
|
end
|
|
|
|
def self.push_notification_url
|
|
"#{base_url}/send_push"
|
|
end
|
|
|
|
def self.events_url
|
|
"#{base_url}/events"
|
|
end
|
|
|
|
def self.billing_base_url
|
|
"#{base_url}/billing"
|
|
end
|
|
|
|
def self.installation_identifier
|
|
identifier = InstallationConfig.find_by(name: 'INSTALLATION_IDENTIFIER')&.value
|
|
identifier ||= InstallationConfig.create!(name: 'INSTALLATION_IDENTIFIER', value: SecureRandom.uuid).value
|
|
identifier
|
|
end
|
|
|
|
def self.billing_url
|
|
"#{billing_base_url}?installation_identifier=#{installation_identifier}"
|
|
end
|
|
|
|
def self.pricing_plan
|
|
return 'community' unless ChatwootApp.enterprise?
|
|
|
|
InstallationConfig.find_by(name: 'INSTALLATION_PRICING_PLAN')&.value || 'community'
|
|
end
|
|
|
|
def self.pricing_plan_quantity
|
|
return 0 unless ChatwootApp.enterprise?
|
|
|
|
InstallationConfig.find_by(name: 'INSTALLATION_PRICING_PLAN_QUANTITY')&.value || 0
|
|
end
|
|
|
|
def self.support_config
|
|
{
|
|
support_website_token: InstallationConfig.find_by(name: 'CHATWOOT_SUPPORT_WEBSITE_TOKEN')&.value,
|
|
support_script_url: InstallationConfig.find_by(name: 'CHATWOOT_SUPPORT_SCRIPT_URL')&.value,
|
|
support_identifier_hash: InstallationConfig.find_by(name: 'CHATWOOT_SUPPORT_IDENTIFIER_HASH')&.value
|
|
}
|
|
end
|
|
|
|
def self.instance_config
|
|
{
|
|
installation_identifier: installation_identifier,
|
|
installation_version: Chatwoot.config[:version],
|
|
installation_host: URI.parse(ENV.fetch('FRONTEND_URL', '')).host,
|
|
installation_env: ENV.fetch('INSTALLATION_ENV', ''),
|
|
edition: ENV.fetch('CW_EDITION', '')
|
|
}
|
|
end
|
|
|
|
def self.instance_metrics
|
|
{
|
|
accounts_count: fetch_count(Account),
|
|
users_count: fetch_count(User),
|
|
inboxes_count: fetch_count(Inbox),
|
|
conversations_count: fetch_count(Conversation),
|
|
incoming_messages_count: fetch_count(Message.incoming),
|
|
outgoing_messages_count: fetch_count(Message.outgoing),
|
|
additional_information: {}
|
|
}
|
|
end
|
|
|
|
def self.fetch_count(model)
|
|
model.last&.id || 0
|
|
end
|
|
|
|
def self.sync_with_hub
|
|
begin
|
|
info = instance_config
|
|
info = info.merge(instance_metrics) unless ENV['DISABLE_TELEMETRY']
|
|
response = RestClient.post(ping_url, info.to_json, { content_type: :json, accept: :json })
|
|
parsed_response = JSON.parse(response)
|
|
rescue *ExceptionList::REST_CLIENT_EXCEPTIONS => e
|
|
Rails.logger.error "Exception: #{e.message}"
|
|
rescue StandardError => e
|
|
ChatwootExceptionTracker.new(e).capture_exception
|
|
end
|
|
parsed_response
|
|
end
|
|
|
|
def self.register_instance(company_name, owner_name, owner_email)
|
|
info = { company_name: company_name, owner_name: owner_name, owner_email: owner_email, subscribed_to_mailers: true }
|
|
RestClient.post(registration_url, info.merge(instance_config).to_json, { content_type: :json, accept: :json })
|
|
rescue *ExceptionList::REST_CLIENT_EXCEPTIONS => e
|
|
Rails.logger.error "Exception: #{e.message}"
|
|
rescue StandardError => e
|
|
ChatwootExceptionTracker.new(e).capture_exception
|
|
end
|
|
|
|
def self.send_push(fcm_options)
|
|
send_push_with_response(fcm_options)
|
|
rescue *ExceptionList::REST_CLIENT_EXCEPTIONS => e
|
|
Rails.logger.error "Exception: #{e.message}"
|
|
rescue StandardError => e
|
|
ChatwootExceptionTracker.new(e).capture_exception
|
|
end
|
|
|
|
def self.send_push_with_response(fcm_options)
|
|
info = { fcm_options: fcm_options }
|
|
RestClient.post(push_notification_url, info.merge(instance_config).to_json, { content_type: :json, accept: :json })
|
|
end
|
|
|
|
def self.emit_event(event_name, event_data)
|
|
return if ENV['DISABLE_TELEMETRY']
|
|
|
|
info = { event_name: event_name, event_data: event_data }
|
|
RestClient.post(events_url, info.merge(instance_config).to_json, { content_type: :json, accept: :json })
|
|
rescue *ExceptionList::REST_CLIENT_EXCEPTIONS => e
|
|
Rails.logger.error "Exception: #{e.message}"
|
|
rescue StandardError => e
|
|
ChatwootExceptionTracker.new(e).capture_exception
|
|
end
|
|
end
|
|
|
|
ChatwootHub.singleton_class.prepend_mod_with('ChatwootHub')
|