diff --git a/app/controllers/api/v1/widget/integrations/dyte_controller.rb b/app/controllers/api/v1/widget/integrations/dyte_controller.rb
new file mode 100644
index 000000000..0661b4a3c
--- /dev/null
+++ b/app/controllers/api/v1/widget/integrations/dyte_controller.rb
@@ -0,0 +1,36 @@
+class Api::V1::Widget::Integrations::DyteController < Api::V1::Widget::BaseController
+ before_action :set_message
+
+ def add_participant_to_meeting
+ if @message.content_type != 'integrations'
+ return render json: {
+ error: I18n.t('errors.dyte.invalid_message_type')
+ }, status: :unprocessable_entity
+ end
+
+ response = dyte_processor_service.add_participant_to_meeting(
+ @message.content_attributes['data']['meeting_id'],
+ @conversation.contact
+ )
+ render_response(response)
+ end
+
+ private
+
+ def render_response(response)
+ render json: response, status: response[:error].blank? ? :ok : :unprocessable_entity
+ end
+
+ def dyte_processor_service
+ Integrations::Dyte::ProcessorService.new(account: @web_widget.inbox.account, conversation: @conversation)
+ end
+
+ def set_message
+ @message = @web_widget.inbox.messages.find(permitted_params[:message_id])
+ @conversation = @message.conversation
+ end
+
+ def permitted_params
+ params.permit(:website_token, :message_id)
+ end
+end
diff --git a/app/javascript/dashboard/components/widgets/conversation/bubble/Integration.vue b/app/javascript/dashboard/components/widgets/conversation/bubble/Integration.vue
index 1978b9b5a..80843854d 100644
--- a/app/javascript/dashboard/components/widgets/conversation/bubble/Integration.vue
+++ b/app/javascript/dashboard/components/widgets/conversation/bubble/Integration.vue
@@ -14,16 +14,16 @@ export default {
mixins: [inboxMixin],
props: {
messageId: {
- type: Number,
- required: true,
+ type: [String, Number],
+ default: 0,
},
contentAttributes: {
type: Object,
default: () => ({}),
},
inboxId: {
- type: Number,
- required: true,
+ type: [String, Number],
+ default: 0,
},
},
computed: {
diff --git a/app/javascript/dashboard/components/widgets/conversation/bubble/integrations/Dyte.vue b/app/javascript/dashboard/components/widgets/conversation/bubble/integrations/Dyte.vue
index de4b07da0..8fca037f9 100644
--- a/app/javascript/dashboard/components/widgets/conversation/bubble/integrations/Dyte.vue
+++ b/app/javascript/dashboard/components/widgets/conversation/bubble/integrations/Dyte.vue
@@ -30,8 +30,7 @@
+
diff --git a/app/javascript/widget/i18n/locale/en.json b/app/javascript/widget/i18n/locale/en.json
index 6329cdeb3..141e9b102 100644
--- a/app/javascript/widget/i18n/locale/en.json
+++ b/app/javascript/widget/i18n/locale/en.json
@@ -86,5 +86,11 @@
"BUTTON_TEXT": "Request a conversation transcript",
"SEND_EMAIL_SUCCESS": "The chat transcript was sent successfully",
"SEND_EMAIL_ERROR": "There was an error, please try again"
+ },
+ "INTEGRATIONS": {
+ "DYTE": {
+ "CLICK_HERE_TO_JOIN": "Click here to join",
+ "LEAVE_THE_ROOM": "Leave the call"
+ }
}
}
diff --git a/config/routes.rb b/config/routes.rb
index 06fb29bb3..787f13f75 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -217,6 +217,13 @@ Rails.application.routes.draw do
end
resources :inbox_members, only: [:index]
resources :labels, only: [:create, :destroy]
+ namespace :integrations do
+ resource :dyte, controller: 'dyte', only: [] do
+ collection do
+ post :add_participant_to_meeting
+ end
+ end
+ end
end
end
diff --git a/spec/controllers/api/v1/widget/integrations/dyte_controller_spec.rb b/spec/controllers/api/v1/widget/integrations/dyte_controller_spec.rb
new file mode 100644
index 000000000..5d5ace90b
--- /dev/null
+++ b/spec/controllers/api/v1/widget/integrations/dyte_controller_spec.rb
@@ -0,0 +1,74 @@
+require 'rails_helper'
+
+RSpec.describe '/api/v1/widget/integrations/dyte', type: :request do
+ let(:account) { create(:account) }
+ let(:web_widget) { create(:channel_widget, account: account) }
+ let(:contact) { create(:contact, account: account, email: nil) }
+ let(:contact_inbox) { create(:contact_inbox, contact: contact, inbox: web_widget.inbox) }
+ let(:conversation) { create(:conversation, contact: contact, account: account, inbox: web_widget.inbox, contact_inbox: contact_inbox) }
+ let(:payload) { { source_id: contact_inbox.source_id, inbox_id: web_widget.inbox.id } }
+ let(:token) { ::Widget::TokenService.new(payload: payload).generate_token }
+ let(:message) { create(:message, conversation: conversation, account: account, inbox: conversation.inbox) }
+ let!(:integration_message) do
+ create(:message, content_type: 'integrations',
+ content_attributes: { type: 'dyte', data: { meeting_id: 'm_id' } },
+ conversation: conversation, account: account, inbox: conversation.inbox)
+ end
+
+ before do
+ create(:integrations_hook, :dyte, account: account)
+ end
+
+ describe 'POST /api/v1/widget/integrations/dyte/add_participant_to_meeting' do
+ context 'when token is invalid' do
+ it 'returns error' do
+ post add_participant_to_meeting_api_v1_widget_integrations_dyte_url,
+ params: { website_token: web_widget.website_token },
+ as: :json
+
+ expect(response).to have_http_status(:not_found)
+ end
+ end
+
+ context 'when token is valid' do
+ context 'when message is not an integration message' do
+ it 'returns error' do
+ post add_participant_to_meeting_api_v1_widget_integrations_dyte_url,
+ headers: { 'X-Auth-Token' => token },
+ params: { website_token: web_widget.website_token, message_id: message.id },
+ as: :json
+
+ expect(response).to have_http_status(:unprocessable_entity)
+ response_body = JSON.parse(response.body)
+ expect(response_body['error']).to eq('Invalid message type. Action not permitted')
+ end
+ end
+
+ context 'when message is an integration message' do
+ before do
+ stub_request(:post, 'https://api.cluster.dyte.in/v1/organizations/org_id/meetings/m_id/participant')
+ .to_return(
+ status: 200,
+ body: { success: true, data: { authResponse: { userAdded: true, id: 'random_uuid', auth_token: 'json-web-token' } } }.to_json,
+ headers: { 'Content-Type' => 'application/json' }
+ )
+ end
+
+ it 'returns authResponse' do
+ post add_participant_to_meeting_api_v1_widget_integrations_dyte_url,
+ headers: { 'X-Auth-Token' => token },
+ params: { website_token: web_widget.website_token, message_id: integration_message.id },
+ as: :json
+
+ expect(response).to have_http_status(:success)
+ response_body = JSON.parse(response.body)
+ expect(response_body['authResponse']).to eq(
+ {
+ 'userAdded' => true, 'id' => 'random_uuid', 'auth_token' => 'json-web-token'
+ }
+ )
+ end
+ end
+ end
+ end
+end