Feature: Twilio Whatsapp Integration (#779)
Twilio Whatsapp Integration Co-authored-by: Sojan <sojan@pepalo.com>
This commit is contained in:
parent
168042f9a4
commit
0cb7333977
1
Gemfile
1
Gemfile
@ -17,6 +17,7 @@ gem 'jbuilder'
|
||||
gem 'kaminari'
|
||||
gem 'responders'
|
||||
gem 'rest-client'
|
||||
gem 'telephone_number'
|
||||
gem 'time_diff'
|
||||
gem 'tzinfo-data'
|
||||
gem 'valid_email2'
|
||||
|
||||
@ -448,6 +448,7 @@ GEM
|
||||
faraday
|
||||
inflecto
|
||||
virtus
|
||||
telephone_number (1.4.6)
|
||||
thor (0.20.3)
|
||||
thread_safe (0.3.6)
|
||||
time_diff (0.3.0)
|
||||
@ -560,6 +561,7 @@ DEPENDENCIES
|
||||
spring
|
||||
spring-watcher-listen
|
||||
telegram-bot-ruby
|
||||
telephone_number
|
||||
time_diff
|
||||
twilio-ruby (~> 5.32.0)
|
||||
twitty!
|
||||
|
||||
@ -21,13 +21,14 @@ class ContactBuilder
|
||||
phone_number: contact_attributes[:phone_number],
|
||||
email: contact_attributes[:email],
|
||||
identifier: contact_attributes[:identifier],
|
||||
additional_attributes: contact_attributes[:identifier]
|
||||
additional_attributes: contact_attributes[:additional_attributes]
|
||||
)
|
||||
contact_inbox = ::ContactInbox.create!(
|
||||
contact_id: contact.id,
|
||||
inbox_id: inbox.id,
|
||||
source_id: source_id
|
||||
)
|
||||
|
||||
::ContactAvatarJob.perform_later(contact, contact_attributes[:avatar_url]) if contact_attributes[:avatar_url]
|
||||
contact_inbox
|
||||
rescue StandardError => e
|
||||
|
||||
@ -15,7 +15,6 @@ class Messages::Outgoing::NormalBuilder
|
||||
|
||||
def perform
|
||||
@message = @conversation.messages.build(message_params)
|
||||
@message.save
|
||||
if @attachments.present?
|
||||
@attachments.each do |uploaded_attachment|
|
||||
attachment = @message.attachments.new(
|
||||
@ -24,8 +23,8 @@ class Messages::Outgoing::NormalBuilder
|
||||
)
|
||||
attachment.file.attach(uploaded_attachment)
|
||||
end
|
||||
@message.save
|
||||
end
|
||||
@message.save
|
||||
@message
|
||||
end
|
||||
|
||||
|
||||
@ -2,14 +2,16 @@ class Api::V1::Accounts::Channels::TwilioChannelsController < Api::BaseControlle
|
||||
before_action :authorize_request
|
||||
|
||||
def create
|
||||
ActiveRecord::Base.transaction do
|
||||
authenticate_twilio
|
||||
build_inbox
|
||||
setup_webhooks
|
||||
setup_webhooks if @twilio_channel.sms?
|
||||
rescue Twilio::REST::TwilioError => e
|
||||
render_could_not_create_error(e.message)
|
||||
rescue StandardError => e
|
||||
render_could_not_create_error(e.message)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@ -26,25 +28,30 @@ class Api::V1::Accounts::Channels::TwilioChannelsController < Api::BaseControlle
|
||||
::Twilio::WebhookSetupService.new(inbox: @inbox).perform
|
||||
end
|
||||
|
||||
def phone_number
|
||||
medium == 'sms' ? permitted_params[:phone_number] : "whatsapp:#{permitted_params[:phone_number]}"
|
||||
end
|
||||
|
||||
def medium
|
||||
permitted_params[:medium]
|
||||
end
|
||||
|
||||
def build_inbox
|
||||
ActiveRecord::Base.transaction do
|
||||
twilio_sms = current_account.twilio_sms.create(
|
||||
@twilio_channel = current_account.twilio_sms.create!(
|
||||
account_sid: permitted_params[:account_sid],
|
||||
auth_token: permitted_params[:auth_token],
|
||||
phone_number: permitted_params[:phone_number]
|
||||
phone_number: phone_number,
|
||||
medium: medium
|
||||
)
|
||||
@inbox = current_account.inboxes.create(
|
||||
name: permitted_params[:name],
|
||||
channel: twilio_sms
|
||||
channel: @twilio_channel
|
||||
)
|
||||
rescue StandardError => e
|
||||
render_could_not_create_error(e.message)
|
||||
end
|
||||
end
|
||||
|
||||
def permitted_params
|
||||
params.require(:twilio_channel).permit(
|
||||
:account_id, :phone_number, :account_sid, :auth_token, :name
|
||||
:account_id, :phone_number, :account_sid, :auth_token, :name, :medium
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@ -23,7 +23,9 @@ class Twilio::CallbackController < ApplicationController
|
||||
:FromZip,
|
||||
:Body,
|
||||
:ToCountry,
|
||||
:FromState
|
||||
:FromState,
|
||||
:MediaUrl0,
|
||||
:MediaContentType0
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
BIN
app/javascript/dashboard/assets/images/channels/whatsapp.png
Normal file
BIN
app/javascript/dashboard/assets/images/channels/whatsapp.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
@ -33,6 +33,14 @@
|
||||
:style="badgeStyle"
|
||||
src="~dashboard/assets/images/twitter-badge.png"
|
||||
/>
|
||||
|
||||
<img
|
||||
v-if="badge === 'Channel::TwilioSms'"
|
||||
id="badge"
|
||||
class="source-badge"
|
||||
:style="badgeStyle"
|
||||
src="~dashboard/assets/images/channels/whatsapp.png"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
<file-upload
|
||||
v-if="showFileUpload"
|
||||
:size="4096 * 4096"
|
||||
accept="jpg,jpeg,png,mp3,ogg,amr,pdf,mp4"
|
||||
@input-file="onFileUpload"
|
||||
>
|
||||
<i
|
||||
@ -142,7 +143,10 @@ export default {
|
||||
return 10000;
|
||||
},
|
||||
showFileUpload() {
|
||||
return this.channelType === 'Channel::WebWidget';
|
||||
return (
|
||||
this.channelType === 'Channel::WebWidget' ||
|
||||
this.channelType === 'Channel::TwilioSms'
|
||||
);
|
||||
},
|
||||
replyButtonLabel() {
|
||||
if (this.isPrivate) {
|
||||
@ -295,6 +299,9 @@ export default {
|
||||
},
|
||||
|
||||
onFileUpload(file) {
|
||||
if (!file) {
|
||||
return;
|
||||
}
|
||||
this.isUploading.image = true;
|
||||
this.$store
|
||||
.dispatch('sendAttachment', [this.currentChat.id, { file: file.file }])
|
||||
|
||||
@ -6,10 +6,26 @@
|
||||
"404": "Diesem Konto sind keine Posteingänge zugeordnet."
|
||||
},
|
||||
"CREATE_FLOW": [
|
||||
{ "title": "Wählen Sie Kanal", "route": "settings_inbox_new", "body": "Wählen Sie den Anbieter, den Sie in Chatwoot integrieren möchten." },
|
||||
{ "title": "Posteingang erstellen", "route": "settings_inboxes_page_channel", "body": "Authentifizieren Sie Ihr Konto und erstellen Sie einen Posteingang." },
|
||||
{ "title": "Agenten hinzufügen", "route": "settings_inboxes_add_agents", "body": "Fügen Sie dem erstellten Posteingang Agenten hinzu." },
|
||||
{ "title": "Voila!", "route": "settings_inbox_finish", "body": "Sie sind bereit zu gehen!" }
|
||||
{
|
||||
"title": "Wählen Sie Kanal",
|
||||
"route": "settings_inbox_new",
|
||||
"body": "Wählen Sie den Anbieter, den Sie in Chatwoot integrieren möchten."
|
||||
},
|
||||
{
|
||||
"title": "Posteingang erstellen",
|
||||
"route": "settings_inboxes_page_channel",
|
||||
"body": "Authentifizieren Sie Ihr Konto und erstellen Sie einen Posteingang."
|
||||
},
|
||||
{
|
||||
"title": "Agenten hinzufügen",
|
||||
"route": "settings_inboxes_add_agents",
|
||||
"body": "Fügen Sie dem erstellten Posteingang Agenten hinzu."
|
||||
},
|
||||
{
|
||||
"title": "Voila!",
|
||||
"route": "settings_inbox_finish",
|
||||
"body": "Sie sind bereit zu gehen!"
|
||||
}
|
||||
],
|
||||
"ADD": {
|
||||
"FB": {
|
||||
@ -35,10 +51,9 @@
|
||||
},
|
||||
"SUBMIT_BUTTON": "Posteingang erstellen"
|
||||
},
|
||||
|
||||
"TWILIO": {
|
||||
"TITLE": "Twilio SMS Channel",
|
||||
"DESC": "Integrieren Sie Twilio und unterstützen Sie Ihre Kunden per SMS.",
|
||||
"TITLE": "Twilio SMS/Whatsapp Channel",
|
||||
"DESC": "Integrieren Sie Twilio und unterstützen Sie Ihre Kunden per SMS/Whatsapp.",
|
||||
"ACCOUNT_SID": {
|
||||
"LABEL": "Account SID",
|
||||
"PLACEHOLDER": "Bitte geben Sie Ihre Twilio Account SID ein",
|
||||
|
||||
@ -6,10 +6,26 @@
|
||||
"404": "There are no inboxes attached to this account."
|
||||
},
|
||||
"CREATE_FLOW": [
|
||||
{ "title": "Choose Channel", "route": "settings_inbox_new", "body": "Choose the provider you want to integrate with Chatwoot." },
|
||||
{ "title": "Create Inbox", "route": "settings_inboxes_page_channel", "body": "Authenticate your account and create an inbox." },
|
||||
{ "title": "Add Agents", "route": "settings_inboxes_add_agents", "body": "Add agents to the created inbox." },
|
||||
{ "title": "Voila!", "route": "settings_inbox_finish", "body": "You are all set to go!" }
|
||||
{
|
||||
"title": "Choose Channel",
|
||||
"route": "settings_inbox_new",
|
||||
"body": "Choose the provider you want to integrate with Chatwoot."
|
||||
},
|
||||
{
|
||||
"title": "Create Inbox",
|
||||
"route": "settings_inboxes_page_channel",
|
||||
"body": "Authenticate your account and create an inbox."
|
||||
},
|
||||
{
|
||||
"title": "Add Agents",
|
||||
"route": "settings_inboxes_add_agents",
|
||||
"body": "Add agents to the created inbox."
|
||||
},
|
||||
{
|
||||
"title": "Voila!",
|
||||
"route": "settings_inbox_finish",
|
||||
"body": "You are all set to go!"
|
||||
}
|
||||
],
|
||||
"ADD": {
|
||||
"FB": {
|
||||
@ -49,13 +65,17 @@
|
||||
"SUBMIT_BUTTON": "Create inbox"
|
||||
},
|
||||
"TWILIO": {
|
||||
"TITLE": "Twilio SMS Channel",
|
||||
"DESC": "Integrate Twilio and start supporting your customers via SMS.",
|
||||
"TITLE": "Twilio SMS/Whatsapp Channel",
|
||||
"DESC": "Integrate Twilio and start supporting your customers via SMS or Whatsapp.",
|
||||
"ACCOUNT_SID": {
|
||||
"LABEL": "Account SID",
|
||||
"PLACEHOLDER": "Please enter your Twilio Account SID",
|
||||
"ERROR": "This field is required"
|
||||
},
|
||||
"CHANNEL_TYPE": {
|
||||
"LABEL": "Channel Type",
|
||||
"ERROR": "Please select your Channel Type"
|
||||
},
|
||||
"AUTH_TOKEN": {
|
||||
"LABEL": "Auth Token",
|
||||
"PLACEHOLDER": "Please enter your Twilio Auth Token",
|
||||
|
||||
@ -23,6 +23,13 @@
|
||||
>
|
||||
{{ contact.email }}
|
||||
</a>
|
||||
<a
|
||||
v-if="contact.phone_number"
|
||||
:href="`tel:${contact.phone_number}`"
|
||||
class="contact--email"
|
||||
>
|
||||
{{ contact.phone_number }}
|
||||
</a>
|
||||
|
||||
<div
|
||||
v-if="
|
||||
@ -211,7 +218,7 @@ export default {
|
||||
text-transform: capitalize;
|
||||
|
||||
font-weight: $font-weight-bold;
|
||||
font-size: $font-size-medium;
|
||||
font-size: $font-size-default;
|
||||
}
|
||||
|
||||
.contact--email {
|
||||
|
||||
@ -14,9 +14,22 @@
|
||||
:placeholder="$t('INBOX_MGMT.ADD.TWILIO.CHANNEL_NAME.PLACEHOLDER')"
|
||||
@blur="$v.channelName.$touch"
|
||||
/>
|
||||
<span v-if="$v.channelName.$error" class="message">
|
||||
{{ $t('INBOX_MGMT.ADD.TWILIO.CHANNEL_NAME.ERROR') }}
|
||||
</span>
|
||||
<span v-if="$v.channelName.$error" class="message">{{
|
||||
$t('INBOX_MGMT.ADD.TWILIO.CHANNEL_NAME.ERROR')
|
||||
}}</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="medium-8 columns">
|
||||
<label :class="{ error: $v.medium.$error }">
|
||||
{{ $t('INBOX_MGMT.ADD.TWILIO.CHANNEL_TYPE.LABEL') }}
|
||||
<select v-model="medium">
|
||||
<option value="sms">SMS</option>
|
||||
<option value="whatsapp">Whatsapp</option>
|
||||
</select>
|
||||
<span v-if="$v.medium.$error" class="message">{{
|
||||
$t('INBOX_MGMT.ADD.TWILIO.CHANNEL_TYPE.ERROR')
|
||||
}}</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@ -29,9 +42,9 @@
|
||||
:placeholder="$t('INBOX_MGMT.ADD.TWILIO.PHONE_NUMBER.PLACEHOLDER')"
|
||||
@blur="$v.phoneNumber.$touch"
|
||||
/>
|
||||
<span v-if="$v.phoneNumber.$error" class="message">
|
||||
{{ $t('INBOX_MGMT.ADD.TWILIO.PHONE_NUMBER.ERROR') }}
|
||||
</span>
|
||||
<span v-if="$v.phoneNumber.$error" class="message">{{
|
||||
$t('INBOX_MGMT.ADD.TWILIO.PHONE_NUMBER.ERROR')
|
||||
}}</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@ -44,9 +57,9 @@
|
||||
:placeholder="$t('INBOX_MGMT.ADD.TWILIO.ACCOUNT_SID.PLACEHOLDER')"
|
||||
@blur="$v.accountSID.$touch"
|
||||
/>
|
||||
<span v-if="$v.accountSID.$error" class="message">
|
||||
{{ $t('INBOX_MGMT.ADD.TWILIO.ACCOUNT_SID.ERROR') }}
|
||||
</span>
|
||||
<span v-if="$v.accountSID.$error" class="message">{{
|
||||
$t('INBOX_MGMT.ADD.TWILIO.ACCOUNT_SID.ERROR')
|
||||
}}</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="medium-8 columns">
|
||||
@ -58,9 +71,9 @@
|
||||
:placeholder="$t('INBOX_MGMT.ADD.TWILIO.AUTH_TOKEN.PLACEHOLDER')"
|
||||
@blur="$v.authToken.$touch"
|
||||
/>
|
||||
<span v-if="$v.authToken.$error" class="message">
|
||||
{{ $t('INBOX_MGMT.ADD.TWILIO.AUTH_TOKEN.ERROR') }}
|
||||
</span>
|
||||
<span v-if="$v.authToken.$error" class="message">{{
|
||||
$t('INBOX_MGMT.ADD.TWILIO.AUTH_TOKEN.ERROR')
|
||||
}}</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@ -92,6 +105,7 @@ export default {
|
||||
return {
|
||||
accountSID: '',
|
||||
authToken: '',
|
||||
medium: '',
|
||||
channelName: '',
|
||||
phoneNumber: '',
|
||||
};
|
||||
@ -106,6 +120,7 @@ export default {
|
||||
phoneNumber: { required, shouldStartWithPlusSign },
|
||||
authToken: { required },
|
||||
accountSID: { required },
|
||||
medium: { required },
|
||||
},
|
||||
methods: {
|
||||
async createChannel() {
|
||||
@ -120,6 +135,7 @@ export default {
|
||||
{
|
||||
twilio_channel: {
|
||||
name: this.channelName,
|
||||
medium: this.medium,
|
||||
account_sid: this.accountSID,
|
||||
auth_token: this.authToken,
|
||||
phone_number: this.phoneNumber,
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
# id :bigint not null, primary key
|
||||
# account_sid :string not null
|
||||
# auth_token :string not null
|
||||
# medium :integer default("sms")
|
||||
# phone_number :string not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
@ -23,6 +24,8 @@ class Channel::TwilioSms < ApplicationRecord
|
||||
validates :auth_token, presence: true
|
||||
validates :phone_number, uniqueness: { scope: :account_id }, presence: true
|
||||
|
||||
enum medium: { sms: 0, whatsapp: 1 }
|
||||
|
||||
belongs_to :account
|
||||
|
||||
has_one :inbox, as: :channel, dependent: :destroy
|
||||
|
||||
@ -70,11 +70,12 @@ class Message < ApplicationRecord
|
||||
has_many :attachments, dependent: :destroy, autosave: true, before_add: :validate_attachments_limit
|
||||
|
||||
after_create :reopen_conversation,
|
||||
:dispatch_event,
|
||||
:send_reply,
|
||||
:execute_message_template_hooks,
|
||||
:notify_via_mail
|
||||
|
||||
# we need to wait for the active storage attachments to be available
|
||||
after_create_commit :dispatch_event, :send_reply
|
||||
|
||||
after_update :dispatch_update_event
|
||||
|
||||
def channel_token
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
class Twilio::IncomingMessageService
|
||||
include ::FileTypeHelper
|
||||
|
||||
pattr_initialize [:params!]
|
||||
|
||||
def perform
|
||||
set_contact
|
||||
set_conversation
|
||||
@conversation.messages.create(
|
||||
@message = @conversation.messages.create(
|
||||
content: params[:Body],
|
||||
account_id: @inbox.account_id,
|
||||
inbox_id: @inbox.id,
|
||||
@ -12,6 +14,7 @@ class Twilio::IncomingMessageService
|
||||
contact_id: @contact.id,
|
||||
source_id: params[:SmsSid]
|
||||
)
|
||||
attach_files
|
||||
end
|
||||
|
||||
private
|
||||
@ -31,6 +34,14 @@ class Twilio::IncomingMessageService
|
||||
@account ||= inbox.account
|
||||
end
|
||||
|
||||
def phone_number
|
||||
twilio_inbox.sms? ? params[:From] : params[:From].gsub('whatsapp:', '')
|
||||
end
|
||||
|
||||
def formatted_phone_number
|
||||
TelephoneNumber.parse(phone_number).international_number
|
||||
end
|
||||
|
||||
def set_contact
|
||||
contact_inbox = ::ContactBuilder.new(
|
||||
source_id: params[:From],
|
||||
@ -61,17 +72,40 @@ class Twilio::IncomingMessageService
|
||||
|
||||
def contact_attributes
|
||||
{
|
||||
name: params[:From],
|
||||
phone_number: params[:From],
|
||||
contact_attributes: additional_attributes
|
||||
name: formatted_phone_number,
|
||||
phone_number: phone_number,
|
||||
additional_attributes: additional_attributes
|
||||
}
|
||||
end
|
||||
|
||||
def additional_attributes
|
||||
if twilio_inbox.sms?
|
||||
{
|
||||
from_zip_code: params[:FromZip],
|
||||
from_country: params[:FromCountry],
|
||||
from_state: params[:FromState]
|
||||
}
|
||||
else
|
||||
{}
|
||||
end
|
||||
end
|
||||
|
||||
def attach_files
|
||||
return if params[:MediaUrl0].blank?
|
||||
|
||||
file_resource = LocalResource.new(params[:MediaUrl0], params[:MediaContentType0])
|
||||
|
||||
attachment = @message.attachments.new(
|
||||
account_id: @message.account_id,
|
||||
file_type: file_type(params[:MediaContentType0])
|
||||
)
|
||||
|
||||
attachment.file.attach(
|
||||
io: file_resource.file,
|
||||
filename: file_resource.tmp_filename,
|
||||
content_type: file_resource.encoding
|
||||
)
|
||||
|
||||
@message.save!
|
||||
end
|
||||
end
|
||||
|
||||
@ -7,11 +7,7 @@ class Twilio::OutgoingMessageService
|
||||
return if inbox.channel.class.to_s != 'Channel::TwilioSms'
|
||||
return unless message.outgoing?
|
||||
|
||||
twilio_message = client.messages.create(
|
||||
body: message.content,
|
||||
from: channel.phone_number,
|
||||
to: contact.phone_number
|
||||
)
|
||||
twilio_message = client.messages.create(message_params)
|
||||
message.update!(source_id: twilio_message.sid)
|
||||
end
|
||||
|
||||
@ -19,6 +15,21 @@ class Twilio::OutgoingMessageService
|
||||
|
||||
delegate :conversation, to: :message
|
||||
delegate :contact, to: :conversation
|
||||
delegate :contact_inbox, to: :conversation
|
||||
|
||||
def message_params
|
||||
params = {
|
||||
body: message.content,
|
||||
from: channel.phone_number,
|
||||
to: contact_inbox.source_id
|
||||
}
|
||||
params[:media_url] = attachments if channel.whatsapp? && message.attachments.present?
|
||||
params
|
||||
end
|
||||
|
||||
def attachments
|
||||
message.attachments.map(&:file_url)
|
||||
end
|
||||
|
||||
def inbox
|
||||
@inbox ||= message.inbox
|
||||
|
||||
5
db/migrate/20200429082655_add_medium_to_twilio_sms.rb
Normal file
5
db/migrate/20200429082655_add_medium_to_twilio_sms.rb
Normal file
@ -0,0 +1,5 @@
|
||||
class AddMediumToTwilioSms < ActiveRecord::Migration[6.0]
|
||||
def change
|
||||
add_column :channel_twilio_sms, :medium, :integer, index: true, default: 0
|
||||
end
|
||||
end
|
||||
@ -10,7 +10,7 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 2020_04_17_093432) do
|
||||
ActiveRecord::Schema.define(version: 2020_04_29_082655) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
@ -121,6 +121,7 @@ ActiveRecord::Schema.define(version: 2020_04_17_093432) do
|
||||
t.integer "account_id", null: false
|
||||
t.datetime "created_at", precision: 6, null: false
|
||||
t.datetime "updated_at", precision: 6, null: false
|
||||
t.integer "medium", default: 0
|
||||
t.index ["account_id", "phone_number"], name: "index_channel_twilio_sms_on_account_id_and_phone_number", unique: true
|
||||
end
|
||||
|
||||
@ -287,11 +288,9 @@ ActiveRecord::Schema.define(version: 2020_04_17_093432) do
|
||||
t.index ["taggable_id", "taggable_type", "context"], name: "index_taggings_on_taggable_id_and_taggable_type_and_context"
|
||||
t.index ["taggable_id", "taggable_type", "tagger_id", "context"], name: "taggings_idy"
|
||||
t.index ["taggable_id"], name: "index_taggings_on_taggable_id"
|
||||
t.index ["taggable_type", "taggable_id"], name: "index_taggings_on_taggable_type_and_taggable_id"
|
||||
t.index ["taggable_type"], name: "index_taggings_on_taggable_type"
|
||||
t.index ["tagger_id", "tagger_type"], name: "index_taggings_on_tagger_id_and_tagger_type"
|
||||
t.index ["tagger_id"], name: "index_taggings_on_tagger_id"
|
||||
t.index ["tagger_type", "tagger_id"], name: "index_taggings_on_tagger_type_and_tagger_id"
|
||||
end
|
||||
|
||||
create_table "tags", id: :serial, force: :cascade do |t|
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
class LocalResource
|
||||
attr_reader :uri
|
||||
|
||||
def initialize(uri)
|
||||
def initialize(uri, file_type = nil)
|
||||
@uri = URI(uri)
|
||||
@file_type = file_type
|
||||
end
|
||||
|
||||
def file
|
||||
@ -23,11 +24,12 @@ class LocalResource
|
||||
io.read.encoding
|
||||
end
|
||||
|
||||
def find_file_type
|
||||
@file_type ? @file_type.split('/').last : Pathname.new(uri.path).extname
|
||||
end
|
||||
|
||||
def tmp_filename
|
||||
[
|
||||
Time.now.to_i.to_s,
|
||||
Pathname.new(uri.path).extname
|
||||
]
|
||||
[Time.now.to_i.to_s, find_file_type].join('.')
|
||||
end
|
||||
|
||||
def tmp_folder
|
||||
|
||||
@ -21,7 +21,8 @@ RSpec.describe '/api/v1/accounts/{account.id}/channels/twilio_channel', type: :r
|
||||
account_sid: 'sid',
|
||||
auth_token: 'token',
|
||||
phone_number: '+1234567890',
|
||||
name: 'SMS Channel'
|
||||
name: 'SMS Channel',
|
||||
medium: 'sms'
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
@ -3,6 +3,7 @@ FactoryBot.define do
|
||||
auth_token { SecureRandom.uuid }
|
||||
account_sid { SecureRandom.uuid }
|
||||
sequence(:phone_number) { |n| "+123456789#{n}1" }
|
||||
medium { :sms }
|
||||
inbox
|
||||
account
|
||||
end
|
||||
|
||||
@ -10,7 +10,9 @@ describe Twilio::OutgoingMessageService do
|
||||
let!(:account) { create(:account) }
|
||||
let!(:widget_inbox) { create(:inbox, account: account) }
|
||||
let!(:twilio_sms) { create(:channel_twilio_sms, account: account) }
|
||||
let!(:twilio_whatsapp) { create(:channel_twilio_sms, medium: :whatsapp, account: account) }
|
||||
let!(:twilio_inbox) { create(:inbox, channel: twilio_sms, account: account) }
|
||||
let!(:twilio_whatsapp_inbox) { create(:inbox, channel: twilio_whatsapp, account: account) }
|
||||
let!(:contact) { create(:contact, account: account) }
|
||||
let(:contact_inbox) { create(:contact_inbox, contact: contact, inbox: twilio_inbox) }
|
||||
let(:conversation) { create(:conversation, contact: contact, inbox: twilio_inbox, contact_inbox: contact_inbox) }
|
||||
@ -55,5 +57,18 @@ describe Twilio::OutgoingMessageService do
|
||||
expect(outgoing_message.reload.source_id).to eq('1234')
|
||||
end
|
||||
end
|
||||
|
||||
it 'if outgoing message has attachment and is for whatsapp' do
|
||||
# check for message attachment url
|
||||
allow(messages_double).to receive(:create).with(hash_including(media_url: [anything])).and_return(message_record_double)
|
||||
allow(message_record_double).to receive(:sid).and_return('1234')
|
||||
|
||||
message = build(
|
||||
:message, message_type: 'outgoing', inbox: twilio_whatsapp_inbox, account: account, conversation: conversation
|
||||
)
|
||||
attachment = message.attachments.new(account_id: message.account_id, file_type: :image)
|
||||
attachment.file.attach(io: File.open(Rails.root.join('spec/assets/avatar.png')), filename: 'avatar.png', content_type: 'image/png')
|
||||
message.save!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Loading…
Reference in New Issue
Block a user