def interpret_cels(self, cels, call): uniqueids = [cel.uniqueid for cel in cels if cel.eventtype == 'CHAN_START'] try: local_channel1, local_channel2, source_channel = starting_channels = uniqueids[:3] except ValueError: # in case a CHAN_START is missing... return call try: local_channel1_start = next(cel for cel in cels if cel.uniqueid == local_channel1 and cel.eventtype == 'CHAN_START') source_channel_answer = next(cel for cel in cels if cel.uniqueid == source_channel and cel.eventtype == 'ANSWER') source_channel_end = next(cel for cel in cels if cel.uniqueid == source_channel and cel.eventtype == 'CHAN_END') local_channel2_answer = next(cel for cel in cels if cel.uniqueid == local_channel2 and cel.eventtype == 'ANSWER') except StopIteration: return call call.date = local_channel1_start.eventtime call.date_end = source_channel_end.eventtime call.source_name = source_channel_answer.cid_name call.source_exten = source_channel_answer.cid_num call.source_line_identity = identity_from_channel(source_channel_answer.channame) participant = find_participant(self._confd, source_channel_answer.channame, role='source') if participant: call.participants.append(participant) call.destination_exten = local_channel2_answer.cid_num local_channel1_app_start = next((cel for cel in cels if cel.uniqueid == local_channel1 and cel.eventtype == 'APP_START'), None) if local_channel1_app_start: call.user_field = local_channel1_app_start.userfield other_channels_start = [cel for cel in cels if cel.uniqueid not in starting_channels and cel.eventtype == 'CHAN_START'] non_local_other_channels = [cel.uniqueid for cel in other_channels_start if not cel.channame.lower().startswith('local/')] other_channels_bridge_enter = [cel for cel in cels if cel.uniqueid in non_local_other_channels and cel.eventtype == 'BRIDGE_ENTER'] destination_channel = other_channels_bridge_enter[-1].uniqueid if other_channels_bridge_enter else None if destination_channel: try: # in outgoing calls, destination ANSWER event has more callerid information than START event destination_channel_answer = next(cel for cel in cels if cel.uniqueid == destination_channel and cel.eventtype == 'ANSWER') # take the last bridge enter/exit to skip local channel optimization destination_channel_bridge_enter = next(reversed([cel for cel in cels if cel.uniqueid == destination_channel and cel.eventtype == 'BRIDGE_ENTER'])) except StopIteration: return call call.destination_name = destination_channel_answer.cid_name call.destination_exten = destination_channel_answer.cid_num call.destination_line_identity = identity_from_channel(destination_channel_answer.channame) participant = find_participant(self._confd, destination_channel_answer.channame, role='destination') if participant: call.participants.append(participant) call.date_answer = destination_channel_bridge_enter.eventtime is_incall = any([True for cel in cels if cel.eventtype == 'XIVO_INCALL']) is_outcall = any([True for cel in cels if cel.eventtype == 'XIVO_OUTCALL']) if is_incall: call.direction = 'inbound' if is_outcall: call.direction = 'outbound' return call
def _change_hold_status(self, channel, new_status): line = identity_from_channel(channel) if line not in self._calls_per_line: logger.warning('No line associated to channel %s to set hold to %s', channel, new_status) return peer_lines = [identity_from_channel(c[PEER_CHANNEL]) for c in self._calls_per_line[line]] for peer_line in peer_lines: for call in self._calls_per_line[peer_line]: if line not in call[PEER_CHANNEL].lower(): continue call[ON_HOLD] = new_status self._current_call_notifier.publish_current_call(peer_line)
def interpret_chan_start(self, cel, call): call.date = cel.eventtime call.source_name = cel.cid_name call.source_exten = cel.cid_num call.requested_exten = cel.exten if cel.exten != 's' else '' call.requested_context = cel.context call.destination_exten = cel.exten if cel.exten != 's' else '' call.source_line_identity = identity_from_channel(cel.channame) participant = find_participant(self._confd, cel.channame) if participant: call.participants.append( CallLogParticipant( role='source', user_uuid=participant['uuid'], line_id=participant['line_id'], tags=participant['tags'], ) ) call.set_tenant_uuid(participant['tenant_uuid']) extension = participant['main_extension'] if extension: call.source_internal_exten = extension['exten'] call.source_internal_context = extension['context'] return call
def _bridge_channels_oriented(self, channel, other_channel): # TODO: PJSIP remove after db migration if channel.startswith('PJSIP/'): line = identity_from_channel(channel[2:]) else: line = identity_from_channel(channel) if line not in self._calls_per_line: self._calls_per_line[line] = [{ PEER_CHANNEL: other_channel, LINE_CHANNEL: channel, BRIDGE_TIME: time.time(), ON_HOLD: False }] self._current_call_notifier.publish_current_call(line) self._check_attended_transfer_target_answered(channel)
def interpret_chan_start(self, cel, call): call.destination_line_identity = identity_from_channel(cel.channame) if call.direction == 'outbound': call.destination_name = '' call.requested_name = '' else: call.destination_exten = cel.cid_num call.destination_name = cel.cid_name if not call.requested_name: call.requested_name = cel.cid_name participant = find_participant(self._confd, cel.channame) if participant: call.participants.append( CallLogParticipant( role='destination', user_uuid=participant['uuid'], line_id=participant['line_id'], tags=participant['tags'], ) ) call.set_tenant_uuid(participant['tenant_uuid']) extension = participant['main_extension'] if extension: call.destination_internal_exten = extension['exten'] call.destination_internal_context = extension['context'] if not call.requested_internal_exten: call.requested_internal_exten = extension['exten'] call.requested_internal_context = extension['context'] return call
def interpret_chan_start(self, cel, call): call.destination_line_identity = identity_from_channel(cel.channame) call.caller_id_by_channels[cel.channame] = (cel.cid_name, cel.cid_num) if call.direction == 'outbound': call.destination_name = '' call.requested_name = '' else: matches = WAIT_FOR_MOBILE_REGEX.match(cel.channame) if matches: call.pending_wait_for_mobile_peers.add(matches.group(1)) elif self._is_a_pending_wait_for_mobile_cel(cel, call): call.interpret_callee_bridge_enter = False call.destination_exten = cel.cid_num call.destination_name = cel.cid_name call.destination_internal_exten = cel.cid_num call.destination_internal_context = cel.context else: call.destination_exten = cel.cid_num call.destination_name = cel.cid_name if not call.requested_name: call.requested_name = cel.cid_name call.raw_participants[cel.channame].update(role='destination') return call
def masquerade(self, old, new): old_2 = self._local_channel_peer(old) line_from_old = identity_from_channel(old) if line_from_old not in self._calls_per_line: logger.debug('No masquerade done for channel %s %s', old, new) return new_2 = self._calls_per_line[line_from_old][0][PEER_CHANNEL] self._execute_masquerade(old, new) self._execute_masquerade(old_2, new_2) line_from_new = identity_from_channel(new) self._current_call_notifier.publish_current_call(line_from_new) line_from_new_2 = identity_from_channel(new_2) self._current_call_notifier.publish_current_call(line_from_new_2)
def interpret_chan_start(self, cel, call): call.destination_line_identity = identity_from_channel(cel.channame) participant = find_participant(self._confd, cel.channame, role='destination') if participant: call.participants.append(participant) return call
def _change_hold_status(self, channel, new_status): line = identity_from_channel(channel) if line not in self._calls_per_line: logger.warning( 'No line associated to channel %s to set hold to %s', channel, new_status) return peer_lines = [ identity_from_channel(c[PEER_CHANNEL]) for c in self._calls_per_line[line] ] for peer_line in peer_lines: for call in self._calls_per_line[peer_line]: if line not in call[PEER_CHANNEL].lower(): continue call[ON_HOLD] = new_status self._current_call_notifier.publish_current_call(peer_line)
def _remove_call(self, channel): line = identity_from_channel(channel) calls = self._calls_per_line[line] new_calls = [call for call in calls if call[LINE_CHANNEL] != channel] if new_calls: self._calls_per_line[line] = new_calls else: del self._calls_per_line[line]
def _find_call(self, channel): line = identity_from_channel(channel) calls = self._calls_per_line.get(line) if not calls: return None for call in calls: if call[LINE_CHANNEL] == channel: return call return None
def set_transfer_channel(self, channel, transfer_channel): line = identity_from_channel(channel) if line not in self._calls_per_line: return for call in self._calls_per_line[line]: if call[LINE_CHANNEL] != channel: continue call[TRANSFER_CHANNEL] = transfer_channel
def interpret_chan_start(self, cel, call): call.date = cel.eventtime call.source_name = cel.cid_name call.source_exten = cel.cid_num call.destination_exten = cel.exten if cel.exten != 's' else '' call.source_line_identity = identity_from_channel(cel.channame) participant = find_participant(self._confd, cel.channame, role='source') if participant: call.participants.append(participant) return call
def interpret_chan_start(self, cel, call): call.date = cel.eventtime call.source_name = cel.cid_name call.source_internal_name = cel.cid_name call.source_exten = call.extension_filter.filter(cel.cid_num) call.requested_exten = call.extension_filter.filter(cel.exten) call.requested_context = cel.context call.destination_exten = call.extension_filter.filter(cel.exten) call.source_line_identity = identity_from_channel(cel.channame) call.raw_participants[cel.channame].update(role='source') return call
def _bridge_channels_oriented(self, channel, other_channel): line = identity_from_channel(channel) if line not in self._calls_per_line: self._calls_per_line[line] = [ {PEER_CHANNEL: other_channel, LINE_CHANNEL: channel, BRIDGE_TIME: time.time(), ON_HOLD: False} ] self._current_call_notifier.publish_current_call(line) line_calls = self._calls_per_line[line] if self._attended_transfer_from_line_is_answered(line_calls, other_channel): self._current_call_notifier.attended_transfer_answered(line)
def set_transfer_channel(self, channel, transfer_channel): if transfer_channel.endswith(';1'): return line = identity_from_channel(channel) if line not in self._calls_per_line: return for call in self._calls_per_line[line]: if call[LINE_CHANNEL] != channel: continue call[TRANSFER_CHANNEL] = transfer_channel self._unanswered_transfers[transfer_channel] = channel
def _bridge_channels_oriented(self, channel, other_channel): line = identity_from_channel(channel) if line not in self._calls_per_line: self._calls_per_line[line] = [{ PEER_CHANNEL: other_channel, LINE_CHANNEL: channel, BRIDGE_TIME: time.time(), ON_HOLD: False }] self._current_call_notifier.publish_current_call(line) line_calls = self._calls_per_line[line] if self._attended_transfer_from_line_is_answered( line_calls, other_channel): self._current_call_notifier.attended_transfer_answered(line)
def _check_attended_transfer_target_answered(self, transfer_channel): transferer_channel = self._unanswered_transfers.get(transfer_channel) if not transferer_channel: return line = identity_from_channel(transferer_channel) line_calls = self._calls_per_line.get(line) if not line_calls: return for line_call in line_calls: if line_call[LINE_CHANNEL] == transferer_channel: self._current_call_notifier.attended_transfer_answered(line) del self._unanswered_transfers[transfer_channel] break
def channels_from_identity(self, identity): return [channel for channel in self.innerdata.channels if identity_from_channel(channel) == identity]
def channels_from_identity(self, identity): identity = identity.lower() return [ channel for channel in self.innerdata.channels if identity_from_channel(channel) == identity ]