/** @format */ import SIPml from 'ecmascript-webrtc-sipml'; import { toast } from 'react-hot-toast'; import outcomingringTone from '../sounds/ringtone.wav'; import waitRingTone from '../sounds/ringbacktone.wav'; import pickSound from '../sounds/dtmf.wav'; export class BoxDialer { sTransferNumber; oRingTone; oRingbackTone; oSipStack; oSipSessionRegister; oSipSessionCall; oSipSessionTransferCall; videoRemote; videoLocal; audioRemote; bFullScreen = false; oNotifICall; bDisableVideo = false; viewVideoLocal; viewVideoRemote; viewLocalScreencast; // <video> (webrtc) or <div> (webrtc4all) oConfigCall; oReadyStateTimer; ringtone; ringbacktone; sipState; soundBool; onSipStateChange = {}; callEvetsBoxDialer; timer = { time: 0, type: null, }; testTimer; constructor() { this.played = false; document.body.addEventListener('click', () => { this.played = true; }); this.videoRemote = document.createElement('video'); this.videoLocal = document.createElement('video'); this.audioRemote = document.createElement('audio'); this.audioRemote.autoplay = true; document.body.appendChild(this.videoRemote); document.body.appendChild(this.videoLocal); document.body.appendChild(this.audioRemote); this.ringtone = new Audio(outcomingringTone); this.waitRingTone = new Audio(waitRingTone); this.pickSound = new Audio(pickSound); this.ringtone.loop = true; this.waitRingTone.loop = true; this.callEvetsBoxDialer = { callHold: false, callMute: null, }; this.oConfigCall = { audio_remote: this.audioRemote, video_local: this.viewVideoLocal, //this.viewVideoLocal video_remote: this.viewVideoRemote, // this.viewVideoRemote screencast_window_id: 0x00000000, // entire desktop bandwidth: { audio: undefined, video: undefined }, video_size: { minWidth: undefined, minHeight: undefined, maxWidth: undefined, maxHeight: undefined, }, events_listener: { events: '*', listener: (event) => this.onSessionEvent({ type: 'call', event }), }, sip_caps: [ { name: '+g.oma.sip-im' }, { name: 'language', value: '"en,fr"' }, ], }; } startTimer() { console.log('start timer'); this.testTimer = setInterval(() => { this.timer.time = this.timer.time + 1; this.onSipStateChange.setDndTimer(this.timer.time); }, 1000); } stopTimer() { clearInterval(this.testTimer); this.timer.time = 0; this.onSipStateChange.setDndTimer(this.timer.time); } onSoundType({ type, bool }) { console.log( this.ringtone, 'sound', { type, bool }, `body clicked: ${this.played}`, ); if (this.played) { switch (type) { case 'ring': if (bool) { this.ringtone.pause(); this.ringtone.remove(); console.log(this.ringtone, 'sound ringtone'); this.ringtone.play(); } else { this.ringtone.pause(); this.ringtone.remove(); } break; case 'wait': if (bool) { this.waitRingTone.pause(); this.waitRingTone.remove(); console.log(this.waitRingTone, 'sound waitRingTone'); this.waitRingTone.play(); } else { this.waitRingTone.pause(); this.waitRingTone.remove(); } break; case 'pick': if (bool) { this.pickSound.remove(); this.pickSound.pause(); this.pickSound.play(); } else { this.pickSound.pause(); this.pickSound.remove(); } break; default: console.error('onSoundType: Such a sound does not exist'); break; } } } sipRegister = ({ number, secret, wsurl }) => { try { Notification.requestPermission(); SIPml.setDebugLevel( window.localStorage && window.localStorage.getItem('org.doubango.expert.disable_debug') === 'true' ? 'error' : 'info', ); // create SIP stack this.oSipStack = new SIPml.Stack({ realm: wsurl, // 'cld.alovoice.uz:61040', impi: number, //'3003', impu: `sip:${number}@${wsurl}`, //'sip:3003@cld.alovoice.uz:61040', password: secret, //'944ad5', display_name: number, //'3003', websocket_proxy_url: `wss://${wsurl}/ws`, //'wss://cld.alovoice.uz:61040/ws', // outbound_proxy_url: '', //(window.localStorage ? window.localStorage.getItem('org.doubango.expert.sip_outboundproxy_url') : null), ice_servers: [{ url: 'stun:stun.l.google.com:19302' }], //(window.localStorage ? window.localStorage.getItem('org.doubango.expert.ice_servers') : null), enable_rtcweb_breaker: true, //(window.localStorage ? window.localStorage.getItem('org.doubango.expert.enable_rtcweb_breaker') == "true" : false), events_listener: { events: '*', listener: (event) => this.onSessionEvent({ type: 'stack', event }), }, enable_early_ims: true, //(window.localStorage ? window.localStorage.getItem('org.doubango.expert.disable_early_ims') != "true" : true), // Must be true unless you're using a real IMS network enable_media_stream_cache: true, //(window.localStorage ? window.localStorage.getItem('org.doubango.expert.enable_media_caching') == "true" : false), //bandwidth: (window.localStorage ? tsk_string_to_object(window.localStorage.getItem('org.doubango.expert.bandwidth')) : null), // could be redefined a session-level //video_size: (window.localStorage ? tsk_string_to_object(window.localStorage.getItem('org.doubango.expert.video_size')) : null), // could be redefined a session-level sip_headers: [ { name: 'User-Agent', value: 'Alovoice-client/v1.0-2023.08.08', }, { name: 'Organization', value: 'Technounit' }, ], }); if (this.oSipStack.start() !== 0) { console.log('<b>Failed to start the SIP stack</b>'); } else return; } catch (e) { console.log('<b>2:' + e + '</b>'); } }; register() { if (this.oSipSessionRegister) this.oSipSessionRegister.unregister(); this.oSipSessionRegister = this.oSipStack.newSession('register', { expires: 200, events_listener: { events: '*', listener: (event) => { this.onSessionEvent({ type: 'register', event }); return event; }, }, }); this.oSipSessionRegister.register(); } callBxMethods({ bxMethodName, bxFuncParams, callback }) { if (window.BX24 && window.BX24.placement) { window?.BX24.placement.call(bxMethodName, bxFuncParams, callback); } else if (window.alovoicePhone && window.alovoicePhone.callMethods) { window.alovoicePhone.callMethods[bxMethodName](bxFuncParams, callback); } } setGuiPhoneState({ stateCode, funcName, funcParam }) { if (window?.alovoice_wsphone) { let uiState = ''; switch (stateCode) { case 'i_new_call': uiState = 'incoming'; break; case 'connected': uiState = 'connected'; break; default: break; } this.callBxMethods({ bxMethodName: 'CallCardSetUiState', bxFuncParams: { uiState }, callback: (e) => { console.log(e, `CallCardSetUiState method done ${e}`); }, }); } else { if (this.onSipStateChange[funcName] !== 'undefined') { this.onSipStateChange[funcName](funcParam); } } } bxLog(...datas) { console.log(`%c BXLOG:`, datas, 'background-color: red;'); } onSessionEvent({ type, event }) { this.sipState = type + '_' + event?.type; console.log('---onSessionEvent EVENT [' + this.sipState + ']', event); switch (this.sipState) { case 'register_stopping': case 'register_stoped': case 'register_failed_to_start': case 'register_failed_to_stop': this.oSipStack = null; this.oSipSessionRegister = null; this.oSipSessionCall = null; break; case 'register_terminated': // оторвался break; case 'register_connected': this.onSipStateChange.dynamicValue('connected'); break; case 'register_connecting': this.onSipStateChange.dynamicValue('pending'); break; case 'stack_started': this.register(); break; case 'call_connecting': this.setGuiPhoneState({ funcName: 'modalState', funcParam: { bool: true, callType: 'outcoming', callAnswerType: null, }, }); break; case 'call_connected': // QORA EKRANDA ULANYAPTI.. SOZINI VAHTGA OZGARTIRISH KERE ( SEKKUNDAMER ) break; case 'hangup_terminating': // QORA EKRANNI OCHIRISH KERE this.setGuiPhoneState({ funcName: 'modalState', funcParam: { bool: false, callType: 'outcoming', callAnswerType: null, }, }); break; case 'call_terminated': console.log('%c call_terminated', 'background-color: yellow;'); this.onSoundType({ type: 'ring', bool: false }); this.setGuiPhoneState({ funcName: 'modalState', funcParam: { bool: false, callType: 'outcoming', callAnswerType: null, callFromName: null, }, }); break; case 'stack_i_new_call': this.oSipSessionCall = event.newSession; this.oSipSessionCall.setConfiguration(this.oConfigCall); this.onSoundType({ type: 'ring', bool: true }); this.setGuiPhoneState({ funcName: 'modalState', funcParam: { bool: true, callType: '', callAnswerType: null, callFromName: event?.o_event?.o_session?.o_uri_from?.s_user_name, }, }); break; case 'stack_stopped': this.register(); break; default: break; } } selectUser() { BX.Runtime.loadExtension('ui.entity-selector').then((exports) => { const { Dialog, TagSelector } = exports; const dialog = new BX.UI.EntitySelector.Dialog({ // targetNode: button, enableSearch: true, multiple: false, context: 'MY_MODULE_CONTEXT', entities: [ { id: 'user', // пользователи options: { selectFields: ['ufPhoneInner'] }, }, { id: 'department', // структура компании: выбор только пользователей }, ], events: { '_Item:onSelect': (event) => { const { item } = event.getData(); const dialog = event.getTarget(); const selectedItems = dialog.getSelectedItems(); if (item.customData.get('ufPhoneInner')) { this.transferButtonClick(item.customData.get('ufPhoneInner')); } }, get 'Item:onSelect'() { return this['_Item:onSelect']; }, set 'Item:onSelect'(value) { this['_Item:onSelect'] = value; }, }, }); dialog.show(); }); } // call_connected; setSipStateChangeCallback(callback, funcName) { this.onSipStateChange[funcName] = callback.bind(this); } sipHangUp() { console.log('sipHangUp'); } sipUnRegister() { console.log('sipUnRegister'); } sipTransfer() { console.log('sipTransfer'); } initialized(phoneNumber, phone) { // if (phoneNumber == phone) { // toast.error('Please enter another number'); // return; // } console.log('initialized argument', phoneNumber); this.callBxMethods({ bxMethodName: 'CallCardSetUiState', bxFuncParams: { uiState: 'connectingOutgoing' }, callback: (e) => { console.log(e, `CallCardSetUiState method done ${e}`); }, }); let phoneNumberString = phoneNumber.toString(); if (phoneNumberString.length) { this.oSipSessionCall = this.oSipStack.newSession( 'call-audio', this.oConfigCall, ); this.oSipSessionCall.call(phoneNumberString); } else { toast.error('Do not correct number', { style: { zIndex: '99999999999999999', }, }); } } stopCall() { this.onSoundType({ type: 'ring', bool: false }); this.onSipStateChange.modalState({ bool: false, callType: 'answered', callAnswerType: 'oncoming', callFromName: null, }); if (this.oSipSessionCall) { this.oSipSessionCall.hangup({ events_listener: { events: '*', listener: (event) => this.onSessionEvent({ type: 'hangup', event }), }, }); } } skipButtonClick() { this.onSoundType({ type: 'ring', bool: false }); this.stopCall(); } answerButtonClick() { this.onSipStateChange.modalState({ bool: true, callType: 'answered', callAnswerType: 'oncoming', }); this.oSipSessionCall.accept(this.oConfigCall); this.onSoundType({ type: 'ring', bool: false }); } sipSendDTMF(c) { if (this.oSipSessionCall && c) { this.oSipSessionCall.dtmf(c); } } addCommentButtonClick() { console.log('addCommentButtonClick'); } muteButtonClick() { console.log(this.callEvetsBoxDialer, 'dsadfdssad INSET'); this.callEvetsBoxDialer = { ...this.callEvetsBoxDialer, callMute: !this.oSipSessionCall.bMute, }; this.oSipSessionCall.mute('audio', this.callEvetsBoxDialer.callMute); this.oSipSessionCall.bMute = this.callEvetsBoxDialer.callMute; this.onSipStateChange.setCallEvents(this.callEvetsBoxDialer); } holdButtonClick() { if (this.callEvetsBoxDialer.callHold) { this.oSipSessionCall.resume(); this.callEvetsBoxDialer = { ...this.callEvetsBoxDialer, callHold: false, }; } else { this.oSipSessionCall.hold(); this.callEvetsBoxDialer = { ...this.callEvetsBoxDialer, callHold: true, }; } this.oSipSessionCall.bHeld = this.callHold; this.onSipStateChange.setCallEvents(this.callEvetsBoxDialer); } closeButtonClick() { console.log('closeButtonClick'); } transferButtonClick(number) { if (this.oSipSessionCall) { if (this.oSipSessionCall.transfer(number) != 0) { toast.error('Call transfer failed'); return; } toast('Call transfered'); this.onSipStateChange.modalState({ bool: false, callType: 'answered', callAnswerType: 'oncoming', callFromName: null, }); } } cancelTransferButtonClick() { console.log('cancelTransferButtonClick'); } completeTransferButtonClick() { console.log('completeTransferButtonClick'); } nextButtonClick() { console.log('nextButtonClick'); } entityChanged() { console.log('entityChanged'); } qualityMeterClick() { console.log('qualityMeterClick'); } dialpadButtonClick() { console.log('dialpadButtonClick'); } notifyAdminButtonClick() { console.log('notifyAdminButtonClick'); } }