import { spawn } from 'child_process' import split2 from 'split2' import { get } from 'http' import { Readable } from 'streamx' import { fixPath } from 'os-dependent-path-delimiter' import kill from 'tree-kill' const eventRegexps = { callEstablished: /Call established: (.+)/, callReceived: /Incoming call from: ([\+\w]+ )?(\S+) -/, hangUp: /(.+): session closed/, ready: /baresip is ready/, serverConnected: /\[\d+ bindings?\]/ } const options = { host: '127.0.0.1', port: '8000', agent: false } const nop = () => {} const executeCommand = (command) => { options.path = `/?${command}` get(options, nop) } export default class Baresip { constructor (opts) { const { command, args, callbacks } = opts this.connected = false this.processPath = fixPath(command) this.args = args this.callbacks = {} this.stream = new Readable() Object.keys(eventRegexps).forEach((event) => { this.on(event, callbacks[event] === undefined ? () => {} : callbacks[event]) }); [ 'on', 'connect', 'kill', 'reload' ].forEach((method) => { this[method] = this[method].bind(this) }) } accept () { executeCommand('a') } dial (phoneNumber) { executeCommand(`d${phoneNumber}`) } hangUp () { executeCommand('b') } toggleCallMuted () { executeCommand('m') } on (event, callback) { this.callbacks[event] = callback } kill (callback) { kill(this.process.pid, 'SIGKILL', (err) => { if (!err) { this.connected = false if (callback !== undefined) { callback() } } }) } reload () { this.kill(() => this.connect()) } connect () { this.connected = true this.process = spawn(this.processPath, this.args) this.process.stdout.pipe(split2()).on('data', (data) => { const parsedData = `${data}` Object.keys(eventRegexps).forEach((event) => { const matches = parsedData.match(eventRegexps[event]) if ((matches !== null) && (matches.length > 0)) { this.callbacks[event](matches[matches.length - 1]) } }) this.stream.push(parsedData) // console.log(parsedData) }) // this.process.stderr.pipe(split2()).on('data', (data) => this.stream.push(data)) } }