def reload_module(self, module): """ Realiza reload de configuracion de Asterisk usando AMI ATENCION: El comando parece estar blacklisted. """ manager = AMIManagerConnector() manager._ami_manager('command', 'module reload {0}'.format(module))
def reload_music_on_hold_config(self): """Realiza reload de configuracion de Asterisk usando AMI """ # TODO: Actualmente el comando manager.command(content) del metodo _ami_action # esta devolviendo estos headers: # {'Response': 'Error', 'ActionID': 'xxx', 'Message': 'Command blacklisted'} manager = AMIManagerConnector() manager.connect() manager._ami_manager('command', 'module unload res_musiconhold.so') time.sleep(2) manager._ami_manager('command', 'module load res_musiconhold.so') manager.disconnect()
def reload_asterisk(self): """Realiza reload de configuracion de Asterisk usando AMI """ manager = AMIManagerConnector() manager.connect() manager._ami_manager('command', 'module reload') manager.disconnect()
class SupervisorActivityAmiManager(object): EXTENSIONES = [ "AGENTLOGOUT", "AGENTUNPAUSE", "AGENTPAUSE", "CHANTAKECALL", "CHANSPYWISHPER", "CHANSPY", "CHANCONFER" ] manager = AMIManagerConnector() def originate_call(self, originate_data): content = originate_data data_returned = self.manager._ami_manager('originate', content) return data_returned def _obtener_agentes_activos(self): agentes_parseados = AgentesParsing() agentes_activos = [] data_returned, error = self.manager._ami_manager( "command", "database show OML/AGENT") agentes_activos = agentes_parseados._parsear_datos_agentes( data_returned) return agentes_activos def ejecutar_accion_sobre_agente(self, supervisor, agente_id, exten): agente_profile = AgenteProfile.objects.get(id=agente_id) agent_activity = AgentActivityAmiManager() supervisor_activity = SupervisorActivityAmiManager() if exten not in self.EXTENSIONES: return _("La acción indicada no existe") channel = "PJSIP/{0}".format(supervisor.sip_extension) channel_vars = { 'OMLAGENTID': str(agente_id), } originate_data = [channel, exten, 'oml-sup-actions', channel_vars] # Genero la llamada via originate por AMI if exten == "AGENTLOGOUT": agente_profile.force_logout() agent_activity.logout_agent(agente_profile) elif exten == "AGENTPAUSE": agent_activity.pause_agent(agente_profile, '00') elif exten == "AGENTUNPAUSE": agent_activity.unpause_agent(agente_profile, '00') else: supervisor_activity.originate_call(originate_data)
class AgentActivityAmiManager(object): manager = AMIManagerConnector() def login_agent(self, agente_profile): error = self._close_open_session(agente_profile) # Inicio nueva sesión if not error: error = self.queue_add_remove(agente_profile, 'QueueAdd') if not error: error = self._insert_astb_status(agente_profile, 'login') return error def logout_agent(self, agente_profile): queue_remove_error = self.queue_add_remove(agente_profile, 'QueueRemove') insert_astdb_error = self._insert_astb_status(agente_profile, 'logout') return queue_remove_error, insert_astdb_error def pause_agent(self, agente_profile, pause_id): pause_name = '' queue_pause_error = self.queue_pause_unpause(agente_profile, pause_id, 'pause') if pause_id == '0': pause_name = 'ACW' elif pause_id == '00': pause_name = 'Supervision' else: pause_name = Pausa.objects.activa_by_pauseid(pause_id).nombre insert_astdb_error = self._insert_astb_status( agente_profile, 'PAUSE-' + str(pause_name)) # TODO: Refactorizar para hacer todo en la misma session del AMIManagerConnector if not insert_astdb_error: insert_astdb_error = self.insert_astdb_pause_id( agente_profile, pause_id) return queue_pause_error, insert_astdb_error def unpause_agent(self, agente_profile, pause_id): queue_unpause_error = self.queue_pause_unpause(agente_profile, pause_id, 'unpause') insert_astdb_error = self._insert_astb_status(agente_profile, 'unpause') return queue_unpause_error, insert_astdb_error def get_pause_id(self, pause_id): return pause_id def _get_family(self, agente_profile): agente_family = AgenteFamily() return agente_family._get_nombre_family(agente_profile) def _get_astdb_status_data(self, agente_profile, action): family = self._get_family(agente_profile) tiempo_actual = int(time.time()) key = 'STATUS' if action == 'login' or action == 'unpause': value = 'READY:' + str(tiempo_actual) elif action == 'logout': value = 'OFFLINE:' + str(tiempo_actual) elif 'PAUSE' in action: value = action + ':' + str(tiempo_actual) content = [family, key, value] return content def get_queue_data(self, agente_profile): agent_id = agente_profile.id member_name = agente_profile.get_asterisk_caller_id() queues = QueueMember.objects.obtener_queue_por_agent(agent_id) penalties = QueueMember.objects.obtener_penalty_por_agent(agent_id) sip_extension = agente_profile.sip_extension interface = "PJSIP/" + str(sip_extension).strip('[]') content = [agent_id, member_name, queues, penalties, interface] return content def queue_add_remove(self, agente_profile, action): content = self.get_queue_data(agente_profile) data_returned, error = self.manager._ami_manager(action, content) return error def queue_pause_unpause(self, agente_profile, pause_id, action): if action == 'unpause': pause_state = 'false' elif action == 'pause': pause_state = 'true' content = self.get_queue_data(agente_profile) content.append(pause_id) content.append(pause_state) data_returned, error = self.manager._ami_manager('QueuePause', content) def _insert_astb_status(self, agente_profile, action): content = self._get_astdb_status_data(agente_profile, action) data_returned, error = self.manager._ami_manager('dbput', content) return error def insert_astdb_pause_id(self, agente_profile, pause_id): family = self._get_family(agente_profile) key = 'PAUSE_ID' value = pause_id content = [family, key, value] data_returned, error = self.manager._ami_manager('dbput', content) return error def _close_open_session(self, agente_profile): status, error = self._get_astdb_agent_status(agente_profile) if not error and not status == 'OFFLINE': # Finalizo posibles pausas en curso. error = self.queue_pause_unpause(agente_profile, '', 'unpause') # Finalizo posible sesión en curso. if not error: error = self.queue_add_remove(agente_profile, 'QueueRemove') return error def _get_astdb_agent_status(self, agente_profile): family = self._get_family(agente_profile) data_returned, error = self.manager._ami_manager( "command", "database show {0}".format(family)) if not error: parser = AgentesParsing() agent_data = parser.parsear_datos_agente(data_returned) status = agent_data.get('status', 'OFFLINE') return status, error
def __init__(self, *args, **kwargs): self.manager = AMIManagerConnector()
class AgentActivityAmiManager(object): redis_connection = None def __init__(self, *args, **kwargs): self.manager = AMIManagerConnector() def connect_manager(self): self.manager.connect() def disconnect_manager(self): self.manager.disconnect() def login_agent(self, agente_profile, manage_connection=False): if manage_connection: self.connect_manager() error = self._close_open_session(agente_profile) # Inicio nueva sesión if not error: error = self._queue_add_remove(agente_profile, 'QueueAdd') if not error: error = self._set_agent_redis_status(agente_profile, 'login') if manage_connection: self.disconnect_manager() return error def logout_agent(self, agente_profile, manage_connection=False): if manage_connection: self.connect_manager() queue_remove_error = self._queue_add_remove(agente_profile, 'QueueRemove') if manage_connection: self.disconnect_manager() insert_redis_error = self._set_agent_redis_status(agente_profile, 'logout') return queue_remove_error, insert_redis_error def set_agent_ringing(self, agente_profile, ringing, manage_connection=False): if manage_connection: self.connect_manager() if ringing: insert_redis_error = self._set_agent_redis_status(agente_profile, 'RINGING') else: insert_redis_error = self._set_agent_redis_status(agente_profile, 'READY') return insert_redis_error def pause_agent(self, agente_profile, pause_id, manage_connection=False): pause_name = '' if pause_id == '0': pause_name = 'ACW' elif pause_id == '00': pause_name = 'Supervision' else: pause_name = Pausa.objects.activa_by_pauseid(pause_id).nombre if manage_connection: self.connect_manager() queue_pause_error = self._queue_pause_unpause(agente_profile, pause_id, 'pause') if manage_connection: self.disconnect_manager() insert_redis_error = self._set_agent_pause_redis_status( agente_profile, pause_name, pause_id) return queue_pause_error, insert_redis_error def unpause_agent(self, agente_profile, pause_id, manage_connection=False): # Me aseguro q exista la pausa activa: if pause_id not in ('0', '00'): pause_id = Pausa.objects.activa_by_pauseid(pause_id).id if manage_connection: self.connect_manager() queue_unpause_error = self._queue_pause_unpause(agente_profile, pause_id, 'unpause') if manage_connection: self.disconnect_manager() insert_redis_error = self._set_agent_redis_status(agente_profile, 'unpause') return queue_unpause_error, insert_redis_error def set_agent_as_unavailable(self, agente_profile): self._set_agent_redis_status(agente_profile, 'UNAVAILABLE') def get_pause_id(self, pause_id): return pause_id def _get_family(self, agente_profile): agente_family = AgenteFamily() return agente_family._get_nombre_family(agente_profile) def _get_redis_status_data(self, action): status = action if action == 'login' or action == 'unpause': status = 'READY' elif action == 'logout': status = 'OFFLINE' elif 'PAUSE' in action: status = action elif 'UNAVAILABLE' in action: status = action return { 'STATUS': status, 'TIMESTAMP': str(int(time.time())) } def _get_queue_data(self, agente_profile): agent_id = agente_profile.id member_name = agente_profile.get_asterisk_caller_id() queues = QueueMember.objects.obtener_queue_por_agent(agent_id) penalties = QueueMember.objects.obtener_penalty_por_agent(agent_id) sip_extension = agente_profile.sip_extension interface = "PJSIP/" + str(sip_extension).strip('[]') content = [agent_id, member_name, queues, penalties, interface] return content def _queue_add_remove(self, agente_profile, action): content = self._get_queue_data(agente_profile) data_returned, error = self.manager._ami_manager(action, content) return error def _queue_pause_unpause(self, agente_profile, pause_id, action): if action == 'unpause': pause_state = 'false' elif action == 'pause': pause_state = 'true' content = self._get_queue_data(agente_profile) content.append(pause_id) content.append(pause_state) data_returned, error = self.manager._ami_manager('QueuePause', content) def _close_open_session(self, agente_profile): status, error = self._get_redis_agent_status(agente_profile) if not error and not status == 'OFFLINE': # Finalizo posibles pausas en curso. error = self._queue_pause_unpause(agente_profile, '', 'unpause') # Finalizo posible sesión en curso. if not error: error = self._queue_add_remove(agente_profile, 'QueueRemove') return error def get_redis_connection(self): if self.redis_connection is None: self.redis_connection = redis.Redis( host=settings.REDIS_HOSTNAME, port=settings.CONSTANCE_REDIS_CONNECTION['port'], decode_responses=True) return self.redis_connection def _save_agent_data(self, agente_profile, data): error = False family = self._get_family(agente_profile) redis_connection = self.get_redis_connection() try: redis_connection.hset(family, mapping=data) except redis.exceptions.RedisError: error = True return error def _set_agent_redis_status(self, agente_profile, action): data = self._get_redis_status_data(action) if data['STATUS'] == 'READY' or (('PAUSE' in data['STATUS']) and ('ACW' not in data['STATUS'])): data['CAMPAIGN'] = '' data['CONTACT_NUMBER'] = '' return self._save_agent_data(agente_profile, data) def _set_agent_pause_redis_status(self, agente_profile, pause_name, pause_id): action = 'PAUSE-' + pause_name data = self._get_redis_status_data(action) data['PAUSE_ID'] = pause_id return self._save_agent_data(agente_profile, data) def _get_redis_agent_status(self, agente_profile): family = self._get_family(agente_profile) redis_connection = self.get_redis_connection() status = None error = False try: status = redis_connection.hget(family, 'STATUS') if status is None: error = True except redis.exceptions.RedisError: error = True return status, error
def __init__(self, *args, **kwargs): self.manager = AMIManagerConnector() self.agent_activity = AgentActivityAmiManager()
class SupervisorActivityAmiManager(object): EXTENSIONES = [ "AGENTLOGOUT", "AGENTUNPAUSE", "AGENTPAUSE", "CHANTAKECALL", "CHANSPYWISHPER", "CHANSPY", "CHANCONFER" ] def __init__(self, *args, **kwargs): self.manager = AMIManagerConnector() self.agent_activity = AgentActivityAmiManager() def _originate_call(self, originate_data): self.manager.connect() content = originate_data data_returned = self.manager._ami_manager('originate', content) self.manager.disconnect() return data_returned def obtener_agentes_activos(self): agentes_parseados = AgentesParsing() agentes_activos = [] self.manager.connect() data_returned, error = self.manager._ami_manager( "command", "database show OML/AGENT") self.manager.disconnect() agentes_activos = agentes_parseados._parsear_datos_agentes( data_returned) return agentes_activos def ejecutar_accion_sobre_agente(self, supervisor, agente_id, exten): agente_profile = AgenteProfile.objects.get(id=agente_id) if exten not in self.EXTENSIONES: return _("La acción indicada no existe") channel = "PJSIP/{0}".format(supervisor.sip_extension) channel_vars = { 'OMLAGENTID': str(agente_id), } originate_data = [channel, exten, 'oml-sup-actions', channel_vars] # Genero la llamada via originate por AMI if exten == "AGENTLOGOUT": agente_profile.force_logout() self.agent_activity.logout_agent(agente_profile, manage_connection=True) elif exten == "AGENTPAUSE": self.agent_activity.pause_agent(agente_profile, '00', manage_connection=True) elif exten == "AGENTUNPAUSE": self.agent_activity.unpause_agent(agente_profile, '00', manage_connection=True) else: self._originate_call(originate_data) def escribir_agentes_unavailable_astdb(self): """ Abre una conexion para setear a los agentes como UNAVAILABLE en ASTDB """ self.agent_activity.connect_manager() agentes_profiles = [] # Nota: Accedo al manager del agent_activity para no crear otra conexion user_activity_list, error = self.agent_activity.manager._ami_manager( 'command', 'queue show') for activity_line in user_activity_list.splitlines(): if activity_line.find("Unavailable") != -1: fields_activity = activity_line.split() agente_id = fields_activity[1].split('_')[0] agente_profile = AgenteProfile.objects.get(id=agente_id) if agente_profile not in agentes_profiles: agentes_profiles.append(agente_profile) if agentes_profiles: for agente_profile in agentes_profiles: self.agent_activity.set_agent_as_unavailable( agente_profile, manage_connection=False) self.agent_activity.disconnect_manager()
class SupervisorActivityAmiManager(object): EXTENSIONES = [ "AGENTLOGOUT", "AGENTUNPAUSE", "AGENTPAUSE", "CHANTAKECALL", "CHANSPYWISHPER", "CHANSPY", "CHANCONFER" ] def __init__(self, *args, **kwargs): self.manager = AMIManagerConnector() self.agent_activity = AgentActivityAmiManager() def _originate_call(self, originate_data): self.manager.connect() content = originate_data data_returned = self.manager._ami_manager('originate', content) self.manager.disconnect() return data_returned def obtener_agentes_activos(self): agentes_activos = [] redis_connection = redis.Redis( host=settings.REDIS_HOSTNAME, port=settings.CONSTANCE_REDIS_CONNECTION['port'], decode_responses=True) # TODO: cambiar a usar el metodo 'scan' que es mas eficiente con datos muy grandes # y realiza una especie de paginación keys_agentes = redis_connection.keys('OML:AGENT*') agentes_activos = [] for key in keys_agentes: agente_info = redis_connection.hgetall(key) status = agente_info.get('STATUS', '') id_agente = key.split(':')[-1] if status != '' and len(agente_info) >= LONGITUD_MINIMA_HEADERS: agente_info['nombre'] = agente_info['NAME'] agente_info['status'] = status agente_info['sip'] = agente_info['SIP'] agente_info['pause_id'] = agente_info.get('PAUSE_ID', '') agente_info['campana_llamada'] = agente_info.get( 'CAMPAIGN', '') agente_info['contacto'] = agente_info.get('CONTACT_NUMBER', '') tiempo_actual = int(time()) tiempo_estado = tiempo_actual - int(agente_info['TIMESTAMP']) agente_info['tiempo'] = tiempo_estado del agente_info['NAME'] del agente_info['STATUS'] del agente_info['TIMESTAMP'] del agente_info['SIP'] agente_info['id'] = int(id_agente) agentes_activos.append(agente_info) return agentes_activos def ejecutar_accion_sobre_agente(self, supervisor, agente_id, exten): agente_profile = AgenteProfile.objects.get(id=agente_id) if exten not in self.EXTENSIONES: return _("La acción indicada no existe") channel = "PJSIP/{0}".format(supervisor.sip_extension) channel_vars = { 'OMLAGENTID': str(agente_id), } originate_data = [channel, exten, 'oml-sup-actions', channel_vars] # Genero la llamada via originate por AMI if exten == "AGENTLOGOUT": agente_profile.force_logout() self.agent_activity.logout_agent(agente_profile, manage_connection=True) elif exten == "AGENTPAUSE": self.agent_activity.pause_agent(agente_profile, '00', manage_connection=True) elif exten == "AGENTUNPAUSE": self.agent_activity.unpause_agent(agente_profile, '00', manage_connection=True) else: self._originate_call(originate_data) def escribir_estado_agentes_unavailable(self): """ Busca en el queue de Asterisk si hay agentes Unavailable para reportarlo en Redis""" self.manager.connect() user_activity_list, error = self.manager._ami_manager( 'command', 'queue show') self.manager.disconnect() agentes_profiles = [] for activity_line in user_activity_list.splitlines(): if activity_line.find("Unavailable") != -1: fields_activity = activity_line.split() agente_id = fields_activity[1].split('_')[0] agente_profile = AgenteProfile.objects.get(id=agente_id) if agente_profile not in agentes_profiles: agentes_profiles.append(agente_profile) if agentes_profiles: for agente_profile in agentes_profiles: self.agent_activity.set_agent_as_unavailable(agente_profile)