Add support for signal usernames
This commit is contained in:
parent
e9afa065b5
commit
1b5f85627c
5 changed files with 88 additions and 17 deletions
|
|
@ -10,10 +10,10 @@
|
|||
|
||||
<% if @signal_notification_enabled: %>
|
||||
<div class="js-signal-phone-container" style="<% if !@signal_has_checked: %>display: none;<% end %>">
|
||||
<h2><%- @T('Signal Phone Number') %></h2>
|
||||
<h2><%- @T('Signal Recipient') %></h2>
|
||||
<div class="form-group">
|
||||
<input type="text" name="signal_uid" class="form-control" value="<%= @signal_uid %>" placeholder="+1234567890">
|
||||
<p class="help-block"><%- @T('Use international format with country code (e.g., +1234567890)') %></p>
|
||||
<input type="text" name="signal_uid" class="form-control" value="<%= @signal_uid %>" placeholder="+1234567890 or u:username.42">
|
||||
<p class="help-block"><%- @T('Phone number (+1234567890) or username with u: prefix (u:john.42)') %></p>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
|
|
|||
|
|
@ -97,16 +97,16 @@ const schema = computed(() => {
|
|||
},
|
||||
]
|
||||
|
||||
// CDR Link: Add Signal phone number field only when Signal notifications are enabled
|
||||
// CDR Link: Add Signal recipient field only when Signal notifications are enabled
|
||||
// AND at least one Signal notification checkbox is selected
|
||||
if (signalNotificationEnabled.value && showSignalPhoneField.value) {
|
||||
baseSchema.push({
|
||||
type: 'text',
|
||||
name: 'signal_uid',
|
||||
label: __('Signal Phone Number'),
|
||||
help: __('Use international format with country code (e.g., +1234567890). Required when Signal notifications are enabled in the matrix.'),
|
||||
label: __('Signal Recipient'),
|
||||
help: __('Phone number (+1234567890) or username with u: prefix (u:john.42)'),
|
||||
props: {
|
||||
placeholder: '+1234567890',
|
||||
placeholder: '+1234567890 or u:username.42',
|
||||
},
|
||||
} as any)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ class CreateTicketFromFormJob < ApplicationJob
|
|||
email = get_field_value(form_data, 'email', mapping)
|
||||
raw_phone = get_field_value(form_data, 'phone', mapping)
|
||||
raw_signal_account = get_field_value(form_data, 'signalAccount', mapping)
|
||||
raw_signal_username = get_field_value(form_data, 'signalUsername', mapping)
|
||||
organization = get_field_value(form_data, 'organization', mapping)
|
||||
type_of_support = get_field_value(form_data, 'typeOfSupport', mapping)
|
||||
description_of_issue = get_field_value(form_data, 'descriptionOfIssue', mapping)
|
||||
|
|
@ -39,10 +40,11 @@ class CreateTicketFromFormJob < ApplicationJob
|
|||
# Sanitize phone numbers
|
||||
phone = sanitize_phone_number(raw_phone)
|
||||
signal_account = sanitize_phone_number(raw_signal_account)
|
||||
signal_username = normalize_signal_username(raw_signal_username)
|
||||
|
||||
# Validate contact info
|
||||
unless email.present? || phone.present? || signal_account.present?
|
||||
raise 'At least one contact method (email, phone, or signalAccount) is required'
|
||||
unless email.present? || phone.present? || signal_account.present? || signal_username.present?
|
||||
raise 'At least one contact method (email, phone, signalAccount, or signalUsername) is required'
|
||||
end
|
||||
|
||||
# Build ticket title
|
||||
|
|
@ -60,7 +62,8 @@ class CreateTicketFromFormJob < ApplicationJob
|
|||
phone: phone,
|
||||
email: email,
|
||||
first_name: first_name,
|
||||
last_name: last_name
|
||||
last_name: last_name,
|
||||
signal_username: signal_username
|
||||
)
|
||||
|
||||
Rails.logger.info "Formstack: Using customer #{customer.id} for ticket"
|
||||
|
|
@ -75,18 +78,20 @@ class CreateTicketFromFormJob < ApplicationJob
|
|||
article_type = Ticket::Article::Type.find_by(name: article_type_name)
|
||||
|
||||
# Check for Signal integration
|
||||
# Use phone number if available, otherwise fall back to username
|
||||
signal_recipient = signal_account.presence || signal_username
|
||||
signal_article_type = nil
|
||||
signal_channel_id = nil
|
||||
signal_bot_token = nil
|
||||
|
||||
if signal_account.present?
|
||||
if signal_recipient.present?
|
||||
signal_channel = Channel.where(area: 'Signal::Number', active: true).first
|
||||
if signal_channel
|
||||
signal_channel_id = signal_channel.id
|
||||
signal_bot_token = signal_channel.options[:bot_token]
|
||||
signal_article_type = Ticket::Article::Type.find_by(name: 'cdr_signal')
|
||||
|
||||
Rails.logger.info "Formstack: Found Signal channel #{signal_channel_id} for Signal ticket"
|
||||
Rails.logger.info "Formstack: Found Signal channel #{signal_channel_id} for Signal ticket (recipient: #{signal_recipient})"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -102,15 +107,15 @@ class CreateTicketFromFormJob < ApplicationJob
|
|||
ticket_data.merge!(zammad_fields)
|
||||
|
||||
# Add Signal preferences if applicable
|
||||
if signal_channel_id && signal_bot_token && signal_article_type && signal_account
|
||||
if signal_channel_id && signal_bot_token && signal_article_type && signal_recipient
|
||||
ticket_data[:preferences] = {
|
||||
channel_id: signal_channel_id,
|
||||
cdr_signal: {
|
||||
bot_token: signal_bot_token,
|
||||
chat_id: signal_account
|
||||
chat_id: signal_recipient
|
||||
}
|
||||
}
|
||||
Rails.logger.info "Formstack: Adding Signal preferences to ticket"
|
||||
Rails.logger.info "Formstack: Adding Signal preferences to ticket (chat_id: #{signal_recipient})"
|
||||
end
|
||||
|
||||
# Create ticket
|
||||
|
|
@ -267,7 +272,7 @@ class CreateTicketFromFormJob < ApplicationJob
|
|||
nil
|
||||
end
|
||||
|
||||
def find_or_create_customer(phone:, email:, first_name:, last_name:)
|
||||
def find_or_create_customer(phone:, email:, first_name:, last_name:, signal_username: nil)
|
||||
customer = nil
|
||||
|
||||
# Try phone first
|
||||
|
|
@ -284,6 +289,11 @@ class CreateTicketFromFormJob < ApplicationJob
|
|||
end
|
||||
end
|
||||
|
||||
# Try Signal username
|
||||
if customer.nil? && signal_username.present?
|
||||
customer = User.find_by(signal_username: signal_username)
|
||||
end
|
||||
|
||||
# Create new customer if not found
|
||||
unless customer
|
||||
user_data = {
|
||||
|
|
@ -296,14 +306,31 @@ class CreateTicketFromFormJob < ApplicationJob
|
|||
}
|
||||
user_data[:email] = email if email.present?
|
||||
user_data[:phone] = phone if phone.present?
|
||||
user_data[:signal_username] = signal_username if signal_username.present?
|
||||
|
||||
customer = User.create!(user_data)
|
||||
Rails.logger.info "Formstack: Created new customer #{customer.id}"
|
||||
end
|
||||
|
||||
# Update existing customer if they don't have username
|
||||
if customer && signal_username.present? && customer.signal_username.blank?
|
||||
customer.update!(signal_username: signal_username)
|
||||
Rails.logger.info "Formstack: Updated customer #{customer.id} with signal_username"
|
||||
end
|
||||
|
||||
customer
|
||||
end
|
||||
|
||||
def normalize_signal_username(raw_username)
|
||||
return nil unless raw_username.present?
|
||||
|
||||
username = raw_username.to_s.strip
|
||||
return nil if username.empty?
|
||||
|
||||
# Add u: prefix if not present
|
||||
username.start_with?('u:') ? username : "u:#{username}"
|
||||
end
|
||||
|
||||
def get_zammad_field_values(form_data, mapping)
|
||||
result = {}
|
||||
zammad_fields = mapping['zammadFields'] || {}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddSignalUsername < ActiveRecord::Migration[5.2]
|
||||
def self.up
|
||||
add_column :users, :signal_username, :string, limit: 50
|
||||
add_index :users, :signal_username
|
||||
User.reset_column_information
|
||||
|
||||
ObjectManager::Attribute.add(
|
||||
force: true,
|
||||
object: 'User',
|
||||
name: 'signal_username',
|
||||
display: 'Signal Username',
|
||||
data_type: 'input',
|
||||
data_option: {
|
||||
type: 'text',
|
||||
maxlength: 50,
|
||||
null: true,
|
||||
item_class: 'formGroup--halfSize',
|
||||
},
|
||||
editable: false,
|
||||
active: true,
|
||||
screens: {
|
||||
signup: {},
|
||||
invite_agent: {},
|
||||
invite_customer: {},
|
||||
edit: { '-all-' => { null: true } },
|
||||
create: { '-all-' => { null: true } },
|
||||
view: { '-all-' => { shown: true } }
|
||||
},
|
||||
to_create: false,
|
||||
to_migrate: false,
|
||||
to_delete: false,
|
||||
position: 721,
|
||||
created_by_id: 1,
|
||||
updated_by_id: 1
|
||||
)
|
||||
end
|
||||
|
||||
def self.down
|
||||
ObjectManager::Attribute.find_by(name: 'signal_username', object: ObjectLookup.find_by(name: 'User'))&.destroy
|
||||
remove_column :users, :signal_username
|
||||
end
|
||||
end
|
||||
|
|
@ -333,7 +333,7 @@ class CdrSignal
|
|||
# Use Signal CLI API
|
||||
api = CdrSignalApi.new
|
||||
|
||||
# Check if we need to create a group (auto-groups enabled, recipient is a phone number)
|
||||
# Check if we need to create a group (auto-groups enabled, recipient is not already a group)
|
||||
is_group_id = recipient.start_with?('group.')
|
||||
final_recipient = recipient
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue