{"version":3,"file":"ion-phoner.cjs","sources":["../src/lib/Phoner.ts","../src/ion-phoner.ts"],"sourcesContent":["import { trace } from \"./utils\";\nimport DefaultListener from \"./DefaultListener\";\nimport SoundControl,{ initSounds } from \"./SoundControl\";\nimport MicroSIPDefault, { ensureMicroSIP } from \"./MicroSIP-shim\";\nconst MicroSIP: any = MicroSIPDefault as any;\n// import \"./MicroSIP\";\n\ndeclare const ConfigurationLoader: any; // Assuming ConfigurationLoader is a global object\n\nexport enum SessionStatus {\n    ESTABLISHED = \"ESTABLISHED\",\n    REGISTERED = \"REGISTERED\",\n    DISCONNECTED = \"DISCONNECTED\",\n    FAILED = \"FAILED\",\n    INCOMING_CALL = \"INCOMING_CALL\",\n    UNREGISTERED = \"UNREGISTERED\",\n    AUTHENTICATION_FAIL = \"AUTHENTICATION_FAIL\"\n}\n\nexport enum CallStatus {\n    RING = \"RING\",\n    ESTABLISHED = \"ESTABLISHED\",\n    HOLD = \"HOLD\",\n    FINISH = \"FINISH\",\n    FAILED = \"FAILED\",\n    PENDING = \"PENDING\",\n    RING_MEDIA = \"RING_MEDIA\",\n    BUSY = \"BUSY\",\n    SESSION_PROGRESS = \"SESSION_PROGRESS\"\n}\n\nexport interface SipOptions {\n    login: String|Number;\n    password?: String;\n    authenticationName?: String|Number;\n    domain: String;\n    outboundProxy?: String;\n    port?: Number;\n    useProxy: boolean;\n    registerRequired: boolean;\n}\n\nexport interface Call {\n    id(): string;\n    status(): CallStatus;\n    answer(options: { localVideoDisplay: HTMLElement | null; remoteVideoDisplay: HTMLElement | null; }): void;\n    hangup(): void;\n    sendDTMF(dtmf: string): void;\n    hold(): void;\n    holdForTransfer(): void;\n    unhold(): void;\n    transfer(target: string): void;\n    getStats(callback: (statistics: any) => void): void;\n    caller(): string;\n    callee(): string;\n    on(event: CallStatus, callback: (call: Call) => void): Call;\n    call(): void;\n    muteAudio(): void;\n    unmuteAudio(): void;\n    isAudioMuted(): boolean;\n}\n\nexport interface Session {\n    createCall(options: {\n        callee: String;\n        visibleName: String | Number;\n        localVideoDisplay: HTMLElement;\n        remoteVideoDisplay: HTMLElement;\n        constraints: { audio: boolean; video: boolean; };\n    }): Call;\n    disconnect(): void;\n    on(event: SessionStatus, callback: (session: Session) => void): Session;\n}\n\ninterface Params {\n    credentials:{\n        extension : Number;\n        password : String;\n        host : String;\n        port : Number;\n        ws : String;\n    }\n    config?:{\n        dom?:{\n            localVideo:HTMLElement;\n            remoteVideo:HTMLElement;\n        }\n    }\n}\n\ninterface Credentials {\n    extension : Number;\n    password : String;\n    host : String;\n    port : Number;\n    ws : String;\n}\n\ninterface Callback {\n    [key: string]: (e: any) => any;\n}\n\nclass Phoner {\n    private credentials: Credentials;\n    private microsipListener: DefaultListener | null;\n    public currentCall: Call | null;\n    private session: Session | null;\n    private holdedCall: Call | null;\n    private incomingCall: boolean;\n    private localVideo: HTMLElement;\n    private remoteVideo: HTMLElement;\n    private sipOptions: SipOptions | null;\n    private timerInterval: any; // NodeJS.Timeout | null;\n    private start: number;\n    private min: number;\n    private activities = (actName:string, payload:any)=>{ return {event:actName, payload}  }\n\n    private callback: Callback = {\n                                    \"connectionStatus\": (e: any) => { return e },\n                                    \"registrationStatus\": (e: any) => { return e },\n                                    \"callListen\": (e: any) => { return e },\n                                    \"callStatusListener\": (e: any) => { return e },\n                                    \"dialEstablished\": (e: any) => { return e },\n                                    \"unregistered\": (e: any) => { return e },\n                                    \"info\": (e: any) => { return e },\n                                };\n\n    constructor(params:Params) {\n    \n        // console.log('params.config?.dom?.localVideo ', params.config?.dom?.localVideo );\n        \n\n        this.credentials = params?.credentials ||{};\n        this.microsipListener = null;\n        this.currentCall = null;\n        this.session = null;\n        this.holdedCall = null;\n        this.incomingCall = false;\n        this.localVideo = params.config?.dom?.localVideo as HTMLElement;\n        this.remoteVideo = params.config?.dom?.remoteVideo as HTMLElement;\n        this.sipOptions = null;\n        this.timerInterval = null;\n        this.start = 0;\n        this.min = 0;\n\n        try {\n            // Ensure the MicroSIP UMD bundle is loaded at runtime, then initialize it.\n            ensureMicroSIP().then((ms) => {\n                try { ms.init(); } catch (err) { console.error('MicroSIP.init failed:', err); }\n            }).catch((err) => {\n                console.error('Failed to load MicroSIP:', err);\n            });\n        } catch(e) {\n            console.log('err');\n            console.error(e);\n        }\n    }\n\n    on(event: keyof Callback, handler: (e: any) => any): void {\n        this.callback[event] = handler;\n    }\n\n    activity(handler:(e:any, payload:any)=>any):void{\n        this.activities = handler\n    }\n\n    init(): void {\n        this.microsipListener = new DefaultListener();\n    }\n\n    connect(): void {\n        // Ensure MicroSIP is loaded, then perform connect actions.\n        ensureMicroSIP().then((ms) => {\n            try {\n                if (ms.Browser && ms.Browser.isSafariWebRTC && ms.getMediaProviders && ms.Browser.isSafariWebRTC() && ms.getMediaProviders()[0] === \"WebRTC\") {\n                    ms.playFirstVideo(this.localVideo, true);\n                    ms.playFirstVideo(this.remoteVideo, false);\n                }\n            } catch (e) {\n                console.warn('MicroSIP browser detection/firstVideo failed', e);\n            }\n\n            const me = this;\n            const url = this.credentials.ws;\n\n            this.sipOptions = {} as SipOptions;\n            this.sipOptions.login = this.credentials.extension;\n            this.sipOptions.password = this.credentials.password;\n            this.sipOptions.authenticationName = this.credentials.extension;\n            this.sipOptions.domain = this.credentials.host;\n            this.sipOptions.outboundProxy = this.credentials.host;\n            this.sipOptions.port = this.credentials.port;\n            this.sipOptions.useProxy = true;\n            this.sipOptions.registerRequired = true;\n\n            const connectionOptions = {\n                urlServer: url,\n                sipOptions: this.sipOptions\n            };\n\n            initSounds();\n            ms.createSession(connectionOptions)\n                .on(ms.constants.SESSION_STATUS.ESTABLISHED, function(session: Session) {\n                    me.session = session;\n                    me.connectionStatusListener(ms.constants.SESSION_STATUS.ESTABLISHED);\n                })\n                .on(ms.constants.SESSION_STATUS.REGISTERED, function() {\n                    me.registrationStatusListener(ms.constants.SESSION_STATUS.REGISTERED);\n                })\n                .on(ms.constants.SESSION_STATUS.DISCONNECTED, function() {\n                    me.connectionStatusListener(ms.constants.SESSION_STATUS.DISCONNECTED);\n                })\n                .on(ms.constants.SESSION_STATUS.FAILED, function() {\n                    me.connectionStatusListener(ms.constants.SESSION_STATUS.FAILED);\n                })\n                .on(ms.constants.SESSION_STATUS.INCOMING_CALL, function(call: Call) {\n                    call.on(ms.constants.CALL_STATUS.RING, function() {\n                        me.callStatusListener(call);\n                    }).on(ms.constants.CALL_STATUS.ESTABLISHED, function() {\n                        me.callStatusListener(call);\n                    }).on(ms.constants.CALL_STATUS.HOLD, function() {\n                        me.callStatusListener(call);\n                    }).on(ms.constants.CALL_STATUS.FINISH, function() {\n                        me.callStatusListener(call);\n                        me.incomingCall = false;\n                    }).on(ms.constants.CALL_STATUS.FAILED, function() {\n                        me.callStatusListener(call);\n                        me.incomingCall = false;\n                    });\n                    me.onCallListener(call);\n                });\n\n            trace(\"Phone - connecting\");\n            const status = \"CONNECTING\";\n            this.callback.connectionStatus(status);\n            const payload = {status};\n            this.activities('connectionStatus',{payload});\n        }).catch(err => {\n            console.error('MicroSIP failed to load in connect():', err);\n        });\n     }\n\n    disconnect(): void {\n        trace(\"Phone - disconnect\");\n        if (this.session) {\n            this.session.disconnect();\n        }\n    }\n\n    cancel(): void {\n        if (this.currentCall) {\n            this.hangup();\n        } else {\n\n        }\n    }\n\n    call(callee: string, hasVideo: boolean): void {\n        const me = this;\n        trace(\"Phone - call \" + callee);\n\n\n        const status = \"TRYING\";\n        this.callback.callStatusListener(status);\n        const payload = {status, callNum:callee, callId:null, type:'out'}\n        this.activities('callStatus',{payload});\n\n        const constraints = {\n            audio: true,\n            video: hasVideo\n        };\n\n        if (!this.session) {\n            trace(\"Phone - Session not established. Cannot make a call.\");\n            return;\n        }\n\n        const outCall = this.session.createCall({\n            callee: callee,\n            visibleName: this.sipOptions?.login || '',\n            localVideoDisplay: this.localVideo,\n            remoteVideoDisplay: this.remoteVideo,\n            constraints: constraints\n        }).on(MicroSIP.constants.CALL_STATUS.RING, function(call: Call) {\n            me.callStatusListener(call);\n        }).on(MicroSIP.constants.CALL_STATUS.ESTABLISHED, function(call: Call) {\n            me.callStatusListener(call);\n        }).on(MicroSIP.constants.CALL_STATUS.HOLD, function(call: Call) {\n            me.callStatusListener(call);\n        }).on(MicroSIP.constants.CALL_STATUS.FINISH, function(call: Call) {\n            me.callStatusListener(call);\n        }).on(MicroSIP.constants.CALL_STATUS.FAILED, function(call: Call) {\n            me.callStatusListener(call);\n        });\n\n        outCall.call();\n\n        this.currentCall = outCall;\n    }\n\n    changeVideoState(/* call: Call, enable: boolean */): void {\n        trace(\"Phone - changeVideoState\");\n        console.warn(\"It's not implemented yet\");\n    }\n\n    sendMessage(message: { to: string; body: string; }): void {\n        trace(\"Phone - sendMessage \" + message.to + \" body: \" + message.body);\n        console.warn(\"It's not implemented yet\");\n    }\n\n    answer(): void {\n        if (!this.currentCall) {\n            trace(\"Phone - No current call to answer.\");\n            return;\n        }\n        trace(\"Phone - answer \" + this.currentCall.id());\n        this.microsipListener?.onAnswer(this.currentCall.id());\n        this.currentCall.answer({\n            localVideoDisplay: this.localVideo,\n            remoteVideoDisplay: this.remoteVideo\n        });\n    }\n\n    mute(): void {\n        if (!this.currentCall) {\n            trace(\"Phone - No current call to answer.\");\n            return;\n        }\n        this.currentCall.muteAudio();\n        trace(\"Phone - mute \" + this.currentCall);\n    }\n\n    unmute(): void {\n        if (!this.currentCall) {\n            trace(\"Phone - No current call to answer.\");\n            return;\n        }\n        this.currentCall.unmuteAudio();\n        trace(\"Phone - unmute \" + this.currentCall);\n    }\n\n    hangup(): void {\n        if (!this.currentCall) {\n            trace(\"Phone - No current call to hangup.\");\n            return;\n        }\n        trace(\"Phone - hangup \" + this.currentCall.id() + \" status \" + this.currentCall.status());\n        this.hideFlashAccess();\n        if (this.currentCall.status() == MicroSIP.constants.CALL_STATUS.PENDING) {\n            this.callStatusListener(this.currentCall);\n        } else {\n            this.currentCall.hangup();\n        }\n        this.microsipListener?.onHangup();\n    }\n\n    sendDTMF(dtmf: string): void {\n        if (!this.currentCall) {\n            trace(\"Phone - No current call to send DTMF.\");\n            return;\n        }\n        trace(\"Phone - sendDTMF callId: \" + this.currentCall.id() + \" dtmf: \" + dtmf);\n        this.currentCall.sendDTMF(dtmf);\n        SoundControl.getInstance().playSound(\"POP\");\n    }\n\n    hold(): void {\n        if (!this.currentCall) {\n            trace(\"Phone - No current call to hold.\");\n            return;\n        }\n        trace(\"Phone - hold callId: \" + this.currentCall.id());\n        this.currentCall.hold();\n    }\n\n    holdForTransfer(): void {\n        if (!this.currentCall) {\n            trace(\"Phone - No current call to hold for transfer.\");\n            return;\n        }\n        trace(\"Phone - hold callId: \" + this.currentCall.id());\n        this.currentCall.holdForTransfer();\n    }\n\n    unhold(): void {\n        if (!this.currentCall) {\n            trace(\"Phone - No current call to unhold.\");\n            return;\n        }\n        trace(\"Phone - unhold callId: \" + this.currentCall.id());\n        this.currentCall.unhold();\n    }\n\n    transfer(target: string): void {\n        if (!this.currentCall) {\n            trace(\"Phone - No current call to transfer.\");\n            return;\n        }\n        trace(\"Phone - transfer callId: \" + this.currentCall.id() + \" target: \" + target);\n        this.currentCall.transfer(target);\n    }\n\n    getStatistics(): void {\n        if (!this.currentCall) {\n            trace(\"Phone - No current call to get statistics.\");\n            return;\n        }\n        this.currentCall.getStats(function(statistics: any) {\n            trace(\"Statistics: \" + JSON.stringify(statistics));\n        });\n    }\n\n    hideFlashAccess(): void {\n\n    }\n\n    /* ------------------ LISTENERS ----------------- */\n\n    connectionStatusListener(status: SessionStatus): void {\n        trace(\"Phone - Connection status \" + status);\n        this.callback.connectionStatus(status);\n        const payload = {status}\n        this.activities('connectionStatus',{payload});\n        \n        // this.connectionStatus = status; // Removed unused variable\n        if (status == MicroSIP.constants.SESSION_STATUS.DISCONNECTED ||\n            status == MicroSIP.constants.SESSION_STATUS.FAILED) {\n            if (this.currentCall) {\n                this.callStatusListener(this.currentCall); // Pass the call object\n            }\n            this.currentCall = null;\n            this.holdedCall = null;\n            this.session = null;\n        } else if (status == MicroSIP.constants.SESSION_STATUS.ESTABLISHED) {\n\n        }\n    }\n\n    registrationStatusListener(status: SessionStatus): void {\n        // this.connectionStatus = status; // Removed unused variable\n        trace(\"Phone - registrationStatusListener \" + status);\n        this.callback.registrationStatus(status);\n        const payload = {status}\n        this.activities('registrationStatus',{payload});\n\n        if (status == MicroSIP.constants.SESSION_STATUS.FAILED) {\n            this.viewMessage(\"Register fail, please check your SIP account details.\");\n            this.disconnect();\n        } else if (status == MicroSIP.constants.SESSION_STATUS.UNREGISTERED) {\n            this.viewMessage(\"Unregistered from sip server\");\n            this.disconnect();\n        } else if (status == MicroSIP.constants.SESSION_STATUS.AUTHENTICATION_FAIL) {\n            this.viewMessage(\"Authentication failed, please check your SIP account details.\");\n            this.disconnect();\n        } else {\n            SoundControl.getInstance().playSound(\"REGISTER\");\n            this.microsipListener?.onRegistered();\n        }\n    }\n\n    onCallListener(call: Call): void {\n        const status = call.status();\n        trace(\"Phone - onCallListener \" + call.id() + \" call.status: \" + call.status());\n\n        this.callback.callStatusListener(status);\n\n        const typeCall  = call.caller() == this.credentials.extension.toString() ? \"out\" :\"in\";\n        const callNum   = typeCall===\"in\" ? (call?.caller() ||'') : (call?.callee()||'');\n\n        const payload = {status, callNum:callNum, callId:call.id(), type:typeCall}\n        this.activities('callListen',{payload});\n\n        if (this.currentCall != null) {\n            this.holdedCall = this.currentCall;\n            this.currentCall = call;\n            trace(\"Phone - It seems like a hold: holdedCall: \" + this.holdedCall.id() + \" currentCall: \" + this.currentCall.id());\n        } else {\n            this.incomingCall = true;\n            this.currentCall = call;\n            if (this.incomingCall == true) {\n                this.microsipListener?.onIncomingCall(call.id());\n\n                //incoming call info\n                const status    = \"INCOMING_CALL\"\n                const callNum   = call?.caller() ||'';\n                const payload   = {status, callNum:callNum, callId:call.id()}\n                this.activities('callListen',{payload});\n            }\n            trace(\"Phone - It seems like a new call currentCall: \" + this.currentCall.id() + \" status: \" + this.currentCall.status());\n\n        }\n    }\n\n    callStatusListener(call: Call): void {\n        const status = call.status();\n        trace(\"Phone - callStatusListener call id: \" + call.id() + \" status: \" + status);\n\n        const typeCall  = call.caller() == this.credentials.extension.toString() ? \"out\" :\"in\";\n        const callNum   = typeCall===\"in\" ? (call?.caller() ||'') : (call?.callee()||'');\n\n        this.callback.callStatusListener(status);\n\n        const payload = {status, callNum:callNum, callId:call.id(),type:typeCall}\n        this.activities('callStatus',{payload});\n\n        if (this.currentCall && this.currentCall.id() == call.id()) {\n            if (status == MicroSIP.constants.CALL_STATUS.FAILED) {\n                trace(\"Phone - ... Call is failed...\");\n                this.currentCall = null;\n\n            } else if (status == MicroSIP.constants.CALL_STATUS.FINISH || status == MicroSIP.constants.CALL_STATUS.PENDING) {\n                trace(\"Phone - ... Call is finished...\");\n                SoundControl.getInstance().stopSound(\"RING\");\n                if (this.holdedCall != null) {\n                    trace(\"Phone - ... Finish holded call...\");\n                    this.currentCall = this.holdedCall;\n                    this.holdedCall = null;\n                } else if (this.isCurrentCall(call)) {\n                    trace(\"Phone - ... Finish current call...\");\n                    this.currentCall = null;\n                    this.microsipListener?.onRemoveCall();\n                    SoundControl.getInstance().playSound(\"FINISH\");\n\n                    this.cancel(); // This calls hangup, which might be redundant if the call is already finished.\n                    clearInterval(this.timerInterval);\n                    this.timerInterval = null;\n                }\n            } else if (status == MicroSIP.constants.CALL_STATUS.HOLD) {\n                trace('Phone - ...Call on hold...');\n                if (this.incomingCall) {\n\n                } else {\n\n                }\n\n            } else if (status == MicroSIP.constants.CALL_STATUS.ESTABLISHED) {\n                trace('Phone - ...Talking...');\n\n                this.startTimer();\n\n                SoundControl.getInstance().stopSound(\"RING\");\n            } else if (status == MicroSIP.constants.CALL_STATUS.RING) {\n                trace('Phone - ...Ringing...');\n                if (this.isRingSoundAllowed()) {\n                    SoundControl.getInstance().playSound(\"RING\");\n                }\n            } else if (status == MicroSIP.constants.CALL_STATUS.RING_MEDIA) {\n                trace('Phone - ...Ringing...');\n                SoundControl.getInstance().stopSound(\"RING\");\n            }\n            else if (status == MicroSIP.constants.CALL_STATUS.BUSY) {\n                SoundControl.getInstance().playSound(\"BUSY\");\n            } else if (status == MicroSIP.constants.CALL_STATUS.SESSION_PROGRESS) {\n                trace('Phone - ...Call in Progress...');\n                SoundControl.getInstance().stopSound(\"RING\");\n            }\n        } else {\n            if (this.holdedCall && this.holdedCall.id() == call.id()) {\n                if (call.status() == MicroSIP.constants.CALL_STATUS.FINISH) {\n                    trace(\"It seems we received FINISH status on holdedCall. Just do null the holdedCall.\");\n                    this.holdedCall = null;\n                }\n            }\n        }\n    }\n\n    onTransferStatusListener(event: { status: any; incoming: any; }): void {\n        trace(\"Phone - onTransferStatusListener status:\" + event.status + \" incoming:\" + event.incoming);\n    }\n\n    onTransferEventListener(event: { status: any; incoming: any; }): void {\n        trace(\"Phone - onTransferEventListener status:\" + event.status + \" incoming:\" + event.incoming);\n    }\n\n    parseMsn(fsService: any, mcn: string): void {\n        trace(\"Phone - parseMcn: \" + mcn);\n        console.log('fsService',fsService);\n    }\n\n    recordingStatusListener(recordReport: { report: { mixedFilename: string; }; }): void {\n        trace(\"Phone - recordingStatusListener: \" + recordReport.report.mixedFilename);\n    }\n\n    onDataEventListener(event: { data: any; }): void {\n        trace(\"Phone - onDataEventListener; received data \" + event.data);\n    }\n\n    dataStatusEventListener(event: { status: any; }): void {\n        trace(\"Phone - DataStatusEventListener; received status \" + event.status);\n    }\n\n    viewMessage(message: string): void {\n         trace(\"Message:  \" + message);\n    }\n\n    openVideoView(): void {\n    \n    }\n\n    // talk timer\n    startTimer(): string {\n        const me = this;\n        let timeMin = '00';\n        let timeSec = '00';\n        if (!me.timerInterval) {\n            me.start = 0;\n            me.min = 0;\n            me.timerInterval = setInterval(function () {\n                me.start++;\n                if (me.start > 59) {\n                    me.start = 0;\n                    me.min++;\n                    if (me.min < 10) {\n                        timeMin = \"0\" + me.min;\n                    } else  timeMin = me.min.toString();\n                }\n                if (me.start < 10) {\n                    timeSec = \"0\" + me.start;\n                } else timeSec = me.start.toString();\n            }, 1000);\n        }\n        return `${timeMin}:${timeSec}`;\n    }\n\n    /* ------------- Additional interface functions --------- */\n    isCurrentCall(call: Call): boolean {\n        return this.currentCall != null && this.currentCall.id() == call.id();\n    }\n\n    isRingSoundAllowed(): boolean {\n        try {\n            if (ConfigurationLoader.getInstance().suppressRingOnActiveAudioStream) {\n                trace(\"Phone - isRingSoundAllowed false\");\n                return false;\n            }\n        } catch (error) {\n            // Handle error if ConfigurationLoader or its properties are undefined\n        }\n        trace(\"Phone - isRingSoundAllowed true\");\n        return true;\n    }\n\n    applyCalleeLetterCase(callee: string): string {\n        if (callee) {\n            if (\"uppercase\" == ConfigurationLoader.getInstance().calleeLetterCase) {\n                return callee.toUpperCase();\n            }\n            if (\"lowercase\" == ConfigurationLoader.getInstance().calleeLetterCase) {\n                return callee.toLowerCase();\n            }\n        }\n        return callee;\n    }\n}\n\nexport default Phoner;\n","import api from './api';\nimport Phoner from './lib/Phoner';\nimport Socket from './socket';\nimport decrypt from './lib/decryptor';\n\ninterface Config {\n    credential:{\n        host: string|null;\n        token: string|null;\n        userkey: string|null;\n    };\n    config?:{\n        dom?:{\n            localVideo  : HTMLElement;\n            remoteVideo : HTMLElement;\n        }\n    }\n}\ninterface Callback{\n    [key:string] : (e:any)=>{}\n}\n\nexport default class IonPhoner {\n\n    private phone:Phoner|null = null;\n    private ws:Socket|null = null;\n    private wsAct:Socket|null = null;\n    private sk:string = '';\n    private isConnected:boolean = false;\n    private isRegistered:boolean = false;\n    private isOnCall:boolean = false;\n    private opt:Config = {credential:{host:null,token:null,userkey:null}}\n\n    private callback:Callback = {\n                                    \"connection-status\": (e:any)=>{ return e },\n                                    \"registration-status\": (e:any)=>{ return e },\n                                    \"call-status\": (e:any)=>{ return e },\n                                    \"auto-dial\": (e:any)=>{ return e },\n                                    \"info\": (e:any)=>{ return e },\n                                    \"queue\": (e:any)=>{ return e },\n                                };\n\n    constructor(params:Config){\n        this.opt.credential.host     = params?.credential.host || '';\n        this.opt.credential.token    = params?.credential.token || '';\n        this.opt.credential.userkey  = params?.credential.userkey || '';\n        this.opt.config              = params.config;\n        this.sk                     = this.setSk(params?.credential?.token||'');\n    }\n\n    async connect():Promise<{status:boolean, result:string|null}>{\n        try {\n\n            const self      = this;\n            const host      = this.opt.credential.host as string;\n            const token     = this.opt.credential.token as string;\n            const userkey   = this.opt.credential.userkey as string;\n            \n            if (host.length  && token.length  && userkey.length ){\n                \n                const payload   = {method:'post', data:{userkey}}\n                const url       = `${host}/api/connect`;\n                const data      = await api(url, token, payload);\n                \n                if(data?.status){\n                    const dataKey       = data?.result || ''\n                    const credRaw       = decrypt(this.sk, dataKey);\n                    const cred          = JSON.parse(credRaw);\n                    \n                    const wsHost        = cred?.phoner?.widget?.ws || ''; \n                    const wsToken       = cred?.phoner?.token || ''; \n                    this.ws             = new Socket(wsHost, wsToken);\n                    this.ws.connect()\n\n                    const wsActHost     = cred?.phoner?.remote?.ws || ''; \n                    const wsActToken    = cred?.phoner?.remote.token || ''; \n                    this.wsAct          = new Socket(wsActHost, wsActToken);\n                    this.wsAct.connect()\n\n                    const wsInit        = {\n                                            category:\"activity\",\n                                            name:\"CONNECTION\",\n                                            payload:{\n                                                status:\"DISCONNECTED\"\n                                            }\n                                        }\n                    this.wsSend(wsInit)\n                    \n                    const domConfig     = this.opt.config;\n                    const credentials   = {\n                                            extension: cred?.pbx?.extension || 0, \n                                            password: cred?.pbx?.password || null, \n                                            host: cred?.pbx?.host || null, \n                                            port: cred?.pbx?.port || null, \n                                            ws: cred?.pbx?.ws || null\n                                        }\n                    const params        = {credentials, config:domConfig}\n                    this.phone          = new Phoner(params);\n\n                    this.phone?.init();\n\n                    this.phone.activity((e:any,data:any)=>{\n                        \n                        if(e=='connectionStatus') {\n                            const payload = data?.payload||null;\n                            this.callback['connection-status'](payload);\n                            this.isConnected = payload?.status=='ESTABLISHED';\n                            if(!this.isConnected) this.isRegistered = false;\n\n\n                            const wsInit        = {\n                                                    category:\"activity\",\n                                                    name:\"CONNECTION\",\n                                                    payload:{\n                                                        status:payload?.status||\"CONNECTING\"\n                                                    }\n                                                }\n                            this.wsSend(wsInit)\n                        }\n\n                        if(e=='registrationStatus') {\n                            const payload = data?.payload||null;\n                            this.callback['registration-status'](payload)\n                            this.isRegistered = payload?.status=='REGISTERED';\n\n                            const wsInit        = {\n                                                    category:\"activity\",\n                                                    name:\"REGISTRATION\",\n                                                    payload:{\n                                                        status:payload?.status||\"CONNECTING\"\n                                                    }\n                                                }\n                            this.wsSend(wsInit)\n                        }\n                        if(e=='callStatus') {\n                            const payload = data?.payload||null;\n                            this.callback['call-status'](payload)\n                            this.isOnCall = payload?.status=='ESTABLISHED';\n\n\n\n                            const wsInit        = {\n                                                    category:\"activity\",\n                                                    name:\"CALL_STATUS\",\n                                                    payload:{\n                                                        status  : payload?.status||\"FINISH\",\n                                                        call_id : payload?.callNum||\"\",\n                                                        type    : payload?.type||\"\",\n                                                    }\n                                                }\n                            this.wsSend(wsInit)\n                        }\n                    })\n\n                    this.ws.onMessage((e:any)=>{\n                        // console.log(e);\n                        if(e){}\n                    })\n\n                    this.wsAct.onMessage((e:any)=>{\n                        try {\n                            const msg           = e\n\n                            // console.log('msg', msg);\n                            \n                            const isOnCall      = self.phone?.currentCall ? true : false\n\n                            const sender        = msg.from;\n                            const statusPhone   = {status:true, result:{\n                                                    connection: self.isConnected, registration: self.isRegistered, isOnCall }\n                                                  }\n                            const callbackMsg   = {category:\"CALLBACK\", userkey:sender, message:statusPhone}\n\n                            if(msg?.category ===\"INFO\" && msg.message.action===\"PHONESTATUS\"){ \n                                self.wsAct?.send(JSON.stringify(callbackMsg))\n                            }\n\n                            if(msg?.category ===\"COMMAND\" && msg.message.action===\"DIAL\"){\n                                \n                                self.wsAct?.send(JSON.stringify(callbackMsg))\n\n                                const number    = msg.message.payload.number || null;\n                                \n                                if(!self.phone?.currentCall) self.phone?.call(number, false);\n                            }\n\n                            if(msg?.category ===\"COMMAND\" && msg.message.action===\"HANGUP\"){\n                                self.phone?.hangup();\n                                self.wsAct?.send(JSON.stringify(callbackMsg))\n                            }\n                        } catch (error) {\n                            \n                        }\n                    })\n\n                    return { status: true, result: null };\n                }else{\n                    return { status: false, result: 'invalid credential' };\n                }\n                \n            }else{\n                return { status: false, result: 'invalid credential' };\n            }\n\n        } catch (error) {\n            const message = error && (error as any).message ? (error as any).message : String(error);\n            return { status: false, result: message };\n        }\n    }\n\n    private wsSend(msg:object){\n        if(this.ws){\n            this.ws.send(JSON.stringify(msg))\n        }\n    }\n\n    register(){\n        this.phone?.connect()\n    }\n\n    unregister(){\n        this.phone?.disconnect()\n    }\n\n    call(phone:string){\n        if (!this.isRegistered || !phone.length) {\n            console.log(\"Cannot make a call.\");\n            return;\n        }\n         if(!this.phone?.currentCall)  this.phone?.call(phone, false)\n    }\n\n\n    dtmf(num:string){\n        if (!this.isOnCall || !num.length) {\n            console.log(\"No current call to send DTMF.\");\n            return;\n        }\n\n        this.phone?.sendDTMF(num)\n    }\n\n    hangup(){\n        this.phone?.hangup();\n    }\n\n    answer(){\n        this.phone?.answer();\n    }\n\n    hold(){\n        this.phone?.hold()\n    }\n\n    unhold(){\n        this.phone?.unhold()\n    }\n\n    mute(){\n        this.phone?.mute()\n    }\n\n    unmute(){\n        this.phone?.unmute()\n    }\n\n    private setSk(token:string):string{\n        const passkey   = token?.replaceAll('-','')?.split('')?.reverse()?.join('');\n        const sk        = passkey+'@'+this.opt.credential.userkey;\n        return sk\n    }\n\n    on(event:keyof Callback, handler:(e:any)=>any){\n        try {\n            this.callback[event]=handler   \n        } catch (error) {\n            console.error('invalid event name');\n        }\n    }\n}"],"names":["MicroSIP","MicroSIPDefault","Phoner","actName","payload","e","params","ensureMicroSIP","ms","err","event","handler","DefaultListener","me","url","connectionOptions","initSounds","session","call","status","callee","hasVideo","constraints","outCall","message","trace","dtmf","SoundControl","target","statistics","typeCall","callNum","fsService","mcn","recordReport","timeMin","timeSec","IonPhoner","self","host","token","userkey","data","api","dataKey","credRaw","decrypt","cred","wsHost","wsToken","Socket","wsActHost","wsActToken","wsInit","domConfig","msg","isOnCall","sender","statusPhone","callbackMsg","number","error","phone","num"],"mappings":"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"}