def create(self, transferred_call, initiator_call, context, exten, flow, variables, timeout): try: transferred_channel = self.ari.channels.get( channelId=transferred_call) initiator_channel = self.ari.channels.get(channelId=initiator_call) except ARINotFound: raise TransferCreationError('channel not found') if not ami.extension_exists(self.amid_client, context, exten): raise InvalidExtension(context, exten) if not self.transfer_lock.acquire(initiator_call): raise TransferAlreadyStarted(initiator_call) if not (Channel(transferred_call, self.ari).is_in_stasis() and Channel(initiator_call, self.ari).is_in_stasis()): transfer_state = self.state_factory.make_from_class( TransferStateReadyNonStasis) else: transfer_state = self.state_factory.make_from_class( TransferStateReady) try: new_state = transfer_state.create(transferred_channel, initiator_channel, context, exten, variables, timeout) except Exception: self.transfer_lock.release(initiator_call) raise if flow == 'blind': new_state = new_state.complete() return new_state.transfer
def create_from_user(self, initiator_call, exten, flow, timeout, user_uuid): if not Channel(initiator_call, self.ari).exists(): raise TransferCreationError('initiator channel not found') if Channel(initiator_call, self.ari).user() != user_uuid: raise UserPermissionDenied(user_uuid, {'call': initiator_call}) try: transferred_call = Channel(initiator_call, self.ari).only_connected_channel().id except TooManyChannels as e: raise TooManyTransferredCandidates(e.channels) except NotEnoughChannels as e: raise TransferCreationError('transferred channel not found') context = User(user_uuid, self.confd_client).main_line().context() return self.create(transferred_call, initiator_call, context, exten, flow, variables={}, timeout=timeout)
def hangup_user(self, call_id, user_uuid): channel = Channel(call_id, self._ari) if not channel.exists() or channel.is_local(): raise NoSuchCall(call_id) if channel.user() != user_uuid: raise UserPermissionDenied(user_uuid, {'call': call_id}) self._ari.channels.hangup(channelId=call_id)
def create(self, transferred_channel, initiator_channel, context, exten, variables, timeout): initiator_uuid = Channel(initiator_channel.id, self._ari).user() if initiator_uuid is None: raise TransferCreationError('initiator has no user UUID') transfer_id = str(uuid.uuid4()) try: ari_helpers.convert_transfer_to_stasis(self._ari, self._amid, transferred_channel.id, initiator_channel.id, context, exten, transfer_id, variables, timeout) except ARINotFound: raise TransferCreationError('channel not found') self.transfer = Transfer(transfer_id, initiator_uuid) self.transfer.initiator_call = initiator_channel.id self.transfer.transferred_call = transferred_channel.id self.transfer.status = self.name self._notifier.created(self.transfer) return TransferStateStarting.from_state(self)
def _channel_hold(self, event): channel_id = event['Uniqueid'] logger.debug('marking channel %s on hold', channel_id) ami.set_variable_ami(self.ami, channel_id, 'XIVO_ON_HOLD', '1') user_uuid = Channel(channel_id, self.ari).user() bus_msg = CallOnHoldEvent(channel_id, user_uuid) self.bus_publisher.publish(bus_msg, headers={'user_uuid:{uuid}'.format(uuid=user_uuid): True})
def process_lost_hangups(self): transfers = list(self.state_persistor.list()) logger.debug('Processing lost hangups since last stop...') for transfer in transfers: transfer_state = self.state_factory.make(transfer) if not Channel(transfer.transferred_call, self.ari).exists(): logger.debug('Transferred hangup from transfer %s', transfer.id) transfer_state = transfer_state.transferred_hangup() if not Channel(transfer.initiator_call, self.ari).exists(): logger.debug('Initiator hangup from transfer %s', transfer.id) transfer_state = transfer_state.initiator_hangup() if not Channel(transfer.recipient_call, self.ari).exists(): logger.debug('Recipient hangup from transfer %s', transfer.id) transfer_state = transfer_state.recipient_hangup() logger.debug('Done.')
def create(self, initiator_call, destination, location, completions, timeout, relocate=None): try: relocated_channel = Channel(initiator_call, self.ari).only_connected_channel() except TooManyChannels as e: raise TooManyChannelCandidates(e.channels) except NotEnoughChannels as e: raise RelocateCreationError('relocated channel not found') initiator_channel = Channel(initiator_call, self.ari) if not initiator_channel.exists(): details = {'initiator_call': initiator_call} raise RelocateCreationError('initiator call not found', details) try: destination = self.destination_factory.from_type( destination, location) except InvalidDestination: details = {'destination': destination, 'location': location} raise RelocateCreationError('invalid destination', details) with self.duplicate_relocate_lock: if self.relocates.find_by_channel(initiator_channel.id): raise RelocateAlreadyStarted(initiator_channel.id) if not relocate: relocate = Relocate(self.state_factory) relocate.relocated_channel = relocated_channel.id relocate.initiator_channel = initiator_channel.id relocate.completions = completions relocate.timeout = timeout self.relocates.add(relocate) self.notifier.observe(relocate) with relocate.locked(): relocate.initiate(destination) return relocate
def make_call_from_channel(self, ari, channel): call = Call(channel.id) call.creation_time = channel.json['creationtime'] call.status = channel.json['state'] call.caller_id_name = channel.json['caller']['name'] call.caller_id_number = channel.json['caller']['number'] call.user_uuid = Channel(channel.id, ari).user() call.on_hold = self._get_hold_from_channel_id(ari, channel.id) == '1' call.bridges = [ bridge.id for bridge in ari.bridges.list() if channel.id in bridge.json['channels'] ] call.talking_to = { connected_channel.id: connected_channel.user() for connected_channel in Channel(channel.id, ari).connected_channels() } return call
def complete(self, relocate): completer = RelocateCompleter(self._amid, self._ari) if Channel(relocate.relocated_channel, self._ari).is_in_stasis(): completer.bridge(relocate) try: self._ari.channels.hangup(channelId=relocate.initiator_channel) except ARINotFound: pass except ARIException as e: logger.exception('ARI error: %s', e) relocate.set_state('ended') else: completer.move_to_stasis(relocate) relocate.set_state('waiting_for_relocated')
def create_from_user(self, initiator_call, exten, flow, user_uuid): if not ari_helpers.channel_exists(self.ari, initiator_call): raise TransferCreationError('initiator channel not found') if Channel(initiator_call, self.ari).user() != user_uuid: raise TransferCreationError( 'initiator call does not belong to authenticated user') try: transferred_call = Channel(initiator_call, self.ari).only_connected_channel() except TooManyChannels as e: raise TooManyTransferredCandidates(e.channels) except NotEnoughChannels as e: raise TransferCreationError('transferred channel not found') context = User(user_uuid, self.confd_client).main_line().context() return self.create(transferred_call, initiator_call, context, exten, flow, variables={})
def make_call_from_channel(self, ari, channel): channel_helper = Channel(channel.id, ari) call = Call(channel.id) call.creation_time = channel.json['creationtime'] call.status = channel.json['state'] call.caller_id_name = channel.json['caller']['name'] call.caller_id_number = channel.json['caller']['number'] call.peer_caller_id_name = channel.json['connected']['name'] call.peer_caller_id_number = channel.json['connected']['number'] call.user_uuid = channel_helper.user() call.on_hold = channel_helper.on_hold() call.bridges = [bridge.id for bridge in ari.bridges.list() if channel.id in bridge.json['channels']] call.talking_to = {connected_channel.id: connected_channel.user() for connected_channel in channel_helper.connected_channels()} call.is_caller = channel_helper.is_caller() call.dialed_extension = channel_helper.dialed_extension() return call
def create_from_user(self, initiator_call, destination, location, completions, timeout, user_uuid): if Channel(initiator_call, self.ari).user() != user_uuid: raise UserPermissionDenied(user_uuid, {'call': initiator_call}) if destination == 'line': try: destination_interface = User( user_uuid, self.confd_client).line(location['line_id']).interface() except (InvalidUserUUID, InvalidUserLine): raise RelocateCreationError('invalid line for user', details={ 'user_uuid': user_uuid, 'line_id': location['line_id'] }) destination = 'interface' location['interface'] = destination_interface variables = {} elif destination == 'mobile': try: user = User(user_uuid, self.confd_client) mobile = user.mobile_phone_number() line_context = user.main_line().context() except (InvalidUserUUID, InvalidUserLine): details = {'user_uuid': user_uuid} raise RelocateCreationError( 'invalid user: could not find main line', details=details) destination = 'extension' location = {'exten': mobile, 'context': line_context} variables = {'WAZO_DEREFERENCED_USERUUID': user_uuid} relocate = Relocate(self.state_factory) relocate.initiator = user_uuid relocate.recipient_variables = variables return self.create(initiator_call, destination, location, completions, timeout, relocate=relocate)
def recipient_answered(self, relocate): relocate.events.publish('answered', relocate) if 'answer' in relocate.completions: completer = RelocateCompleter(self._amid, self._ari) if Channel(relocate.relocated_channel, self._ari).is_in_stasis(): completer.bridge(relocate) try: self._ari.channels.hangup( channelId=relocate.initiator_channel) except ARINotFound: pass except ARIException as e: logger.exception('ARI error: %s', e) relocate.set_state('ended') else: completer.move_to_stasis(relocate) relocate.set_state('waiting_for_relocated') elif 'api' in relocate.completions: relocate.set_state('waiting_for_completion') else: raise NotImplementedError()
def create(self, transferred_channel, initiator_channel, context, exten, variables): initiator_uuid = Channel(initiator_channel.id, self._ari).user() if initiator_uuid is None: raise TransferCreationError('initiator has no user UUID') transfer_bridge = self._ari.bridges.create(type='mixing', name='transfer') transfer_id = transfer_bridge.id try: transferred_channel.setChannelVar(variable='XIVO_TRANSFER_ROLE', value='transferred') transferred_channel.setChannelVar(variable='XIVO_TRANSFER_ID', value=transfer_id) initiator_channel.setChannelVar(variable='XIVO_TRANSFER_ROLE', value='initiator') initiator_channel.setChannelVar(variable='XIVO_TRANSFER_ID', value=transfer_id) transfer_bridge.addChannel(channel=transferred_channel.id) transfer_bridge.addChannel(channel=initiator_channel.id) except ARINotFound: raise TransferCreationError('some channel got hung up') try: ari_helpers.hold_transferred_call(self._ari, transferred_channel.id) except ARINotFound: raise TransferCreationError('transferred call hung up') try: self._ari.channels.ring(channelId=initiator_channel.id) except ARINotFound: raise TransferCreationError('initiator call hung up') recipient_call = self._services.originate_recipient(initiator_channel.id, context, exten, transfer_id, variables) self.transfer = Transfer(transfer_id, initiator_uuid) self.transfer.transferred_call = transferred_channel.id self.transfer.initiator_call = initiator_channel.id self.transfer.recipient_call = recipient_call self.transfer.status = self.name self._notifier.created(self.transfer) return TransferStateRingback.from_state(self)
def list_calls_user(self, user_uuid, application_filter=None, application_instance_filter=None): calls = self.list_calls(application_filter, application_instance_filter) return [call for call in calls if call.user_uuid == user_uuid and not Channel(call.id_, self._ari).is_local()]