def holdtime_announce(agi, cursor, args): queue_id = agi.get_variable('XIVO_DSTID') try: queue = objects.Queue(agi, cursor, int(queue_id)) except (ValueError, LookupError) as e: agi.dp_break(str(e)) if queue.announce_holdtime != 1: return holdtime = agi.get_variable('QUEUEHOLDTIME') holdtime = max(1, (int(holdtime) + 59) / 60) gender = 'f' if holdtime == 1 else '' agi.answer() agi.stream_file('queue-holdtime') agi.stream_file('queue-less-than') agi.say_number(str(holdtime), gender=gender) agi.stream_file('queue-minutes') def set_call_record_side(agi, queue): agi.set_variable('WAZO_CALL_RECORD_SIDE', 'caller') agi.set_variable('__WAZO_LOCAL_CHAN_MATCH_UUID', str(uuid4())) agid.register(incoming_queue_set_features) agid.register(holdtime_announce)
# -*- coding: utf-8 -*- # Copyright 2010-2019 The Wazo Authors (see the AUTHORS file) # SPDX-License-Identifier: GPL-3.0-or-later import logging from wazo_agid import agid from wazo_agid import objects logger = logging.getLogger(__name__) def check_schedule(agi, cursor, args): path = agi.get_variable('XIVO_PATH') path_id = agi.get_variable('XIVO_PATH_ID') if not path: return schedule = objects.ScheduleDataMapper.get_from_path(cursor, path, path_id) schedule_state = schedule.compute_state_for_now() agi.set_variable('XIVO_SCHEDULE_STATUS', schedule_state.state) if schedule_state.state == 'closed': schedule_state.action.set_variables_in_agi(agi) # erase path for next schedule check agi.set_variable('XIVO_PATH', '') agid.register(check_schedule)
# -*- coding: utf-8 -*- # Copyright 2013-2019 The Wazo Authors (see the AUTHORS file) # SPDX-License-Identifier: GPL-3.0-or-later from wazo_agid import agid from wazo_agid.handlers.agentfeatures import AgentFeatures def incoming_agent_set_features(agi, cursor, args): agentfeatures_handler = AgentFeatures(agi, cursor, args) agentfeatures_handler.execute() agid.register(incoming_agent_set_features)
if response['total'] != 1: raise Exception("Device with ip {} not found".format(ip)) return response['items'][0] def _get_line(client, provcode): response = client.lines.list(provisioning_code=provcode, recurse=True) if response['total'] != 1: raise Exception( "Line with provisioning code {} not found".format(provcode)) return response['items'][0] def provision(agi, cursor, args): try: client = agi.config['confd']['client'] provcode = args[0] ip_port = args[1] if ':' in ip_port: ip, _ = ip_port.split(':', 1) else: ip = ip_port _do_provision(client, provcode, ip) except Exception as e: logger.error('Error during provisioning: %s', e) else: agi.set_variable('XIVO_PROV_OK', '1') agid.register(provision)
# -*- coding: utf-8 -*- # Copyright 2012-2019 The Wazo Authors (see the AUTHORS file) # SPDX-License-Identifier: GPL-3.0-or-later import logging from wazo_agid import agid from wazo_agid.handlers import agent logger = logging.getLogger(__name__) def agent_get_status(agi, cursor, args): try: tenant_uuid = args[0] agent_id = int(args[1]) agent.get_agent_status(agi, agent_id, tenant_uuid=tenant_uuid) except Exception as e: logger.exception("Error while getting agent status") agi.dp_break(e) agid.register(agent_get_status)
logger.debug("Creating backend, name %s, factory %s", section, backend_factory) backends[section] = backend_factory(**backend_factory_args) logger.debug("Created %s backends", len(backends)) # 4. creation destinations global DESTINATIONS DESTINATIONS = {} for section in filter(lambda s: s.startswith("dstnum_"), config.sections()): cur_destination = section[7:] # 6 == len("dstnum_") cur_backend_ids = map(lambda s: s.strip(), config.get(section, "dest").split(",")) cur_backends = _build_backends_list(backends, cur_backend_ids, cur_destination) logger.debug('Creating destination, dstnum %s, backends %s', cur_destination, cur_backend_ids) DESTINATIONS[cur_destination] = cur_backends logger.debug("Created %s destinations", len(DESTINATIONS)) def _build_backends_list(available_backends, backend_ids, destination): backends = [] for backend_id in backend_ids: if backend_id in available_backends: backends.append(available_backends[backend_id]) else: logger.warning('Destination %s is referencing unknown backend "%s" in xivo_fax.conf', destination, backend_id) return backends agid.register(handle_fax, setup_handle_fax)
# -*- coding: utf-8 -*- # Copyright 2009-2019 The Wazo Authors (see the AUTHORS file) # SPDX-License-Identifier: GPL-3.0-or-later from wazo_agid import agid def monitoring(agi, cursor, args): agi.send_command("Status: OK") agid.register(monitoring)
# -*- coding: utf-8 -*- # Copyright 2019-2021 The Wazo Authors (see the AUTHORS file) # SPDX-License-Identifier: GPL-3.0-or-later from wazo_agid import agid def wake_mobile(agi, cursor, args): user_uuid = args[0] should_wake_mobile = agi.get_variable('WAZO_WAIT_FOR_MOBILE') or False if not should_wake_mobile: return video_enabled = agi.get_variable('WAZO_VIDEO_ENABLED') agi.appexec( 'UserEvent', 'Pushmobile,WAZO_DST_UUID: {},WAZO_VIDEO_ENABLED: {}'.format( user_uuid, video_enabled)) agid.register(wake_mobile)
paging_opts = paging_opts + 'd' if paging.quiet: paging_opts = paging_opts + 'q' if paging.record: paging_opts = paging_opts + 'r' if paging.ignore: paging_opts = paging_opts + 'i' if paging.announcement_play and paging.announcement_file: sound_file_directory = '/var/lib/wazo/sounds/tenants' announcement_file_name = os.path.join( sound_file_directory, paging.tenant_uuid, 'playback', paging.announcement_file, ) paging_opts = paging_opts + u'A({file_name})'.format( file_name=announcement_file_name) if paging.announcement_caller: paging_opts = paging_opts + 'n' return paging_opts agid.register(paging)
skill_rule_id = options[1] skill_rule_variables = options[2] if not skill_rule_id: _set_variables(agi, call, timeout) return with session_scope() as session: skill_rule = session.query(QueueSkillRule).get(int(skill_rule_id)) if not skill_rule: _set_variables(agi, call, timeout) return skill_rule_function = 'skillrule-{}'.format(skill_rule.id) skill_rule_kwargs = [] if skill_rule_variables: skill_rule_variables = skill_rule_variables.replace('|', ',') skill_rule_variables = json.loads(skill_rule_variables) skill_rule_kwargs = ['{}={}'.format(key, value) for key, value in skill_rule_variables.items()] call = '{function}({kwargs})'.format(function=skill_rule_function, kwargs=','.join(skill_rule_kwargs)) _set_variables(agi, call, timeout) def _set_variables(agi, call, timeout): agi.set_variable('XIVO_QUEUESKILLRULESET', call) agi.set_variable('ARG2_TIMEOUT', timeout) agid.register(queue_skill_rule_set)
res = cursor.fetchall() call_rights.apply_rules(agi, res) if outcallid: cursor.query( "SELECT ${columns} FROM rightcall " "INNER JOIN rightcallmember " "ON rightcall.id = rightcallmember.rightcallid " "INNER JOIN outcall " "ON CAST(rightcallmember.typeval AS integer) = outcall.id " "WHERE rightcall.id IN " + rightcallids + " " "AND rightcallmember.type = 'outcall' " "AND outcall.id = %s " "AND rightcall.commented = 0", (call_rights.RIGHTCALL_AUTHORIZATION_COLNAME, call_rights.RIGHTCALL_PASSWD_COLNAME), (outcallid, )) res = cursor.fetchall() call_rights.apply_rules(agi, res) call_rights.allow(agi) def user_set_call_rights(agi, cursor, args): try: _user_set_call_rights(agi, cursor, args) except call_rights.RuleAppliedException: return agid.register(user_set_call_rights)
else: agi.set_variable('CALLERID(num)', callerid_num) return def setup(cursor): global config re_objs.clear() config = ConfigParser.RawConfigParser() config.read([RULES_FILE]) for section_name in config.sections(): try: regexp = config.get(section_name, 'callerid') except ConfigParser.NoOptionError: log.error("option 'callerid' not found in section %r", section_name) sys.exit(1) try: re_obj = re.compile(regexp) except re.error: log.error("invalid regexp %r in section %r", regexp, section_name) sys.exit(1) re_objs[section_name] = re_obj agid.register(in_callerid, setup)
# -*- coding: utf-8 -*- # Copyright 2012-2019 The Wazo Authors (see the AUTHORS file) # SPDX-License-Identifier: GPL-3.0-or-later import logging from wazo_agid import agid from wazo_agid.handlers import agent logger = logging.getLogger(__name__) def agent_login(agi, cursor, args): try: tenant_uuid = args[0] agent_id = int(args[1]) extension = args[2] context = args[3] agent.login_agent(agi, agent_id, extension, context, tenant_uuid) except Exception as e: logger.exception("Error while logging in agent") agi.dp_break(e) agid.register(agent_login)
def phone_progfunckey(agi, cursor, args): userid = agi.get_variable('XIVO_USERID') xlen = len(args) if xlen != 1: agi.dp_break("Invalid number of arguments (args: %r)" % args) try: fklist = split_extension(args[0]) except ValueError as e: agi.dp_break(str(e)) if userid != fklist[0]: agi.dp_break("Wrong userid. (userid: %r, excepted: %r)" % (fklist[0], userid)) feature = "" try: extenfeatures = objects.ExtenFeatures(agi, cursor) feature = extenfeatures.get_name_by_exten(fklist[1]) except LookupError as e: feature = "" agi.verbose(str(e)) agi.set_variable('XIVO_PHONE_PROGFUNCKEY', ''.join(fklist[1:])) agi.set_variable('XIVO_PHONE_PROGFUNCKEY_FEATURE', feature) agid.register(phone_progfunckey)
# -*- coding: utf-8 -*- # Copyright 2012-2019 The Wazo Authors (see the AUTHORS file) # SPDX-License-Identifier: GPL-3.0-or-later import logging from wazo_agid import agid from wazo_agid.handlers import agent logger = logging.getLogger(__name__) def agent_logoff(agi, cursor, args): try: tenant_uuid = args[0] agent_id = int(args[1]) agent.logoff_agent(agi, agent_id, tenant_uuid=tenant_uuid) except Exception as e: logger.exception("Error while logging off agent") agi.dp_break(e) agid.register(agent_logoff)
'Error while retrieving vmbox from number and context', exc_info=True) agi.dp_break(str(e)) else: try: vmboxid = int(agi.get_variable('XIVO_VMBOXID')) vmbox = objects.VMBox(agi, cursor, vmboxid) except (ValueError, LookupError) as e: logger.error('Error while retrieving vmbox from id', exc_info=True) agi.dp_break(str(e)) if vmbox.skipcheckpass: vmmain_options = "s" else: vmmain_options = "" if caller and caller.language: mbox_lang = caller.language elif vmbox.language: mbox_lang = vmbox.language else: mbox_lang = '' agi.set_variable('XIVO_VMMAIN_OPTIONS', vmmain_options) agi.set_variable('XIVO_MAILBOX', vmbox.mailbox) agi.set_variable('XIVO_MAILBOX_CONTEXT', vmbox.context) agi.set_variable('XIVO_MAILBOX_LANGUAGE', mbox_lang) agid.register(vmbox_get_info)
else: _set_diversion(agi, '', '') def _is_hold_time_overrun(agi, queue, waiting_calls): if queue.waittime is None or waiting_calls == 0: return False holdtime = int(agi.get_variable('QUEUEHOLDTIME')) return holdtime > queue.waittime def _is_agent_ratio_overrun(agi, queue, waiting_calls): if queue.waitratio is None or waiting_calls == 0: return False agents = int(agi.get_variable('QUEUE_MEMBER({},logged)'.format( queue.name))) if agents == 0: return True return (waiting_calls + 1.0) / agents > queue.waitratio def _set_diversion(agi, event, dialaction): agi.set_variable('XIVO_DIVERT_EVENT', event) agi.set_variable('XIVO_FWD_TYPE', 'QUEUE_' + dialaction) agid.register(check_diversion)
tmpfile = filepath % "tmp" realfile = filepath % "outgoing" f = open(tmpfile, 'w') f.write("Channel: Local/%s@%s\n" "MaxRetries: 0\n" "RetryTime: 30\n" "WaitTime: 30\n" "CallerID: %s\n" "Set: XIVO_DISACONTEXT=%s\n" "Context: xivo-callbackdisa\n" "Extension: s" % (srcnum, context, srcnum, context)) f.close() os.utime(tmpfile, (mtime, mtime)) os.chown(tmpfile, ASTERISK_UID, ASTERISK_GID) os.rename(tmpfile, realfile) def setup_callback(cursor): global ASTERISK_UID, ASTERISK_GID ASTERISK_UID, ASTERISK_GID = _get_uid_gid("asterisk") def _get_uid_gid(name): pw_name, pw_passwd, pw_uid, pw_gid, pw_gecos, pw_dir, pw_shell = pwd.getpwnam(name) return pw_uid, pw_gid agid.register(callback, setup_callback)
logger.error('Error during enabling call recording: %s', e) def _disable_call_recording(agi, calld, channel_id): try: calld.calls.stop_record(channel_id) except Exception as e: logger.error('Error during disabling call recording: %s', e) def start_mix_monitor(agi, cursor, args): _start_mix_monitor(agi) def _start_mix_monitor(agi): tenant_uuid = agi.get_variable(dialplan_variables.TENANT_UUID) recording_uuid = str(uuid.uuid4()) filename = CALL_RECORDING_FILENAME_TEMPLATE.format( tenant_uuid=tenant_uuid, recording_uuid=recording_uuid, ) mix_monitor_options = agi.get_variable('WAZO_MIXMONITOR_OPTIONS') agi.appexec('MixMonitor', '{},{}'.format(filename, mix_monitor_options)) agi.set_variable('WAZO_CALL_RECORD_ACTIVE', '1') agid.register(call_recording) agid.register(record_caller) agid.register(start_mix_monitor)
# -*- coding: utf-8 -*- # Copyright 2012-2019 The Wazo Authors (see the AUTHORS file) # SPDX-License-Identifier: GPL-3.0-or-later from wazo_agid import agid def callerid_extend(agi, cursor, args): if 'agi_callington' in agi.env: agi.set_variable('XIVO_SRCTON', agi.env['agi_callington']) agid.register(callerid_extend)
# -*- coding: utf-8 -*- # Copyright 2021 The Wazo Authors (see the AUTHORS file) # SPDX-License-Identifier: GPL-3.0-or-later from wazo_agid import agid from wazo_agid.handlers import queue def queue_answered_call(agi, cursor, args): handler = queue.AnswerHandler(agi, cursor, args) handler.execute() agid.register(queue_answered_call)
MEETING_RE = re.compile( r'^wazo-meeting-([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$' ) def meeting_user(agi, cursor, args): tenant_uuid = agi.get_variable('WAZO_TENANT_UUID') try: meeting = _find_meeting(agi, cursor, tenant_uuid, args) except (AttributeError, LookupError, TypeError) as e: agi.verbose('Failed to find meeting {}'.format(e)) agi.answer() agi.stream_file('invalid') return agi.dp_break('Could not find meeting matching {}'.format(args)) agi.set_variable('WAZO_MEETING_UUID', meeting.uuid) agi.set_variable('WAZO_MEETING_NAME', meeting.name) def _find_meeting(agi, cursor, tenant_uuid, args): identifier = args[0] if identifier.isdigit(): return objects.Meeting(agi, cursor, tenant_uuid, number=identifier) else: matches = MEETING_RE.match(identifier) return objects.Meeting(agi, cursor, tenant_uuid, uuid=matches.group(1)) agid.register(meeting_user)
self._user_uuid = user_uuid self.interfaces = [] hint = agi.get_variable('HINT({}@usersharedlines)'.format(user_uuid)) if not hint: raise UnknownUser() for endpoint in hint.split('&'): if '/' not in endpoint: continue for interface in self._find_matching_interfaces(endpoint): self.interfaces.append(interface) def _find_matching_interfaces(self, endpoint): protocol, name = endpoint.split('/', 1) if protocol == 'pjsip': contacts = build_sip_interface(self._agi, self._user_uuid, name) for contact in contacts.split('&'): yield contact else: yield endpoint def get_user_interfaces(agi, cursor, args): user_uuid = args[0] user_line = _UserLine(agi, user_uuid) agi.set_variable('WAZO_USER_INTERFACES', '&'.join(user_line.interfaces)) agid.register(get_user_interfaces)
# -*- coding: utf-8 -*- # Copyright 2021 The Wazo Authors (see the AUTHORS file) # SPDX-License-Identifier: GPL-3.0-or-later from wazo_agid import agid from wazo_agid.handlers import group def group_answered_call(agi, cursor, args): handler = group.AnswerHandler(agi, cursor, args) handler.execute() agid.register(group_answered_call)
# -*- coding: utf-8 -*- # Copyright 2006-2019 The Wazo Authors (see the AUTHORS file) # SPDX-License-Identifier: GPL-3.0-or-later from wazo_agid import agid from wazo_agid.handlers.userfeatures import UserFeatures def incoming_user_set_features(agi, cursor, args): userfeatures_handler = UserFeatures(agi, cursor, args) userfeatures_handler.execute() agid.register(incoming_user_set_features)
def _phone_set_busy(agi, cursor, args): enabled = _phone_set_forward(agi, 'busy', args) if enabled is not None: agi.set_variable('XIVO_BUSYENABLED', int(enabled)) def _phone_set_forward(agi, forward_name, args): try: user_id = _get_id_of_calling_user(agi) result = _user_set_forward(agi, user_id, forward_name, args) except Exception as e: logger.error('Error during setting %s: %s', forward_name, e) return None else: agi.set_variable('XIVO_USERID_OWNER', user_id) return result['enabled'] def _user_set_forward(agi, user_id, forward_name, args): enabled = args[1] == '1' destination = args[2] confd_client = agi.config['confd']['client'] body = {'enabled': enabled} if enabled: body['destination'] = destination confd_client.users(user_id).update_forward(forward_name, body) return body agid.register(phone_set_feature)
_set_reverse_lookup_variable(agi, lookup_result['fields']) except Exception as e: msg = 'Reverse lookup failed: {}'.format(e) logger.info(msg) agi.verbose(msg) def _should_reverse_lookup(cid_name, cid_number): return cid_name == cid_number or cid_name == 'unknown' def _set_new_caller_id(agi, display_name, cid_number): new_caller_id = u'"{}" <{}>'.format(display_name, cid_number) agi.set_callerid(new_caller_id.encode('utf8')) def _set_reverse_lookup_variable(agi, fields): agi.set_variable("XIVO_REVERSE_LOOKUP", _create_reverse_lookup_variable(fields)) def _create_reverse_lookup_variable(fields): variable_content = [] for key, value in fields.iteritems(): variable_content.append(u'db-{}: {}'.format(key, value)) return u','.join(variable_content).encode('utf8') agid.register(callerid_forphones)
def group_member_present(agi, cursors, args): tenant_uuid = args[0] user_uuid = args[1] group_id = int(args[2]) confd_client = agi.config['confd']['client'] try: group_name = confd_client.groups.get(group_id, tenant_uuid=tenant_uuid)['name'] except RequestException as e: logger.error('Error while getting group %s in tenant %s: %s', group_id, tenant_uuid, e) agi.set_variable('WAZO_GROUP_MEMBER_ERROR', e) return group_members = agi.get_variable( 'QUEUE_MEMBER_LIST({group})'.format(group=group_name)) group_members = group_members.split(',') interface = 'Local/{}@usersharedlines'.format(user_uuid) if interface in group_members: agi.set_variable('WAZO_GROUP_MEMBER_PRESENT', '1') else: agi.set_variable('WAZO_GROUP_MEMBER_PRESENT', '0') agid.register(group_member_remove) agid.register(group_member_add) agid.register(group_member_present)
ringtype = CONFIG_PARSER.get(section, referer_origin_fwd) elif CONFIG_PARSER.has_option(section, referer_origin): ringtype = CONFIG_PARSER.get(section, referer_origin) elif forwarded == '1' and CONFIG_PARSER.has_option( section, origin_fwd): ringtype = CONFIG_PARSER.get(section, origin_fwd) elif forwarded == '1' and CONFIG_PARSER.has_option(section, 'forward'): ringtype = CONFIG_PARSER.get(section, 'forward') else: ringtype = CONFIG_PARSER.get(section, origin) phonetype = CONFIG_PARSER.get(section, 'phonetype') except (ConfigParser.NoOptionError, ValueError): logger.debug('Ring type exception', exc_info=True) agi.verbose("Using the native phone ring tone") else: agi.set_variable('XIVO_RINGTYPE', ringtype) agi.set_variable('XIVO_PHONETYPE', phonetype) agi.verbose("Using ring tone %s" % (ringtype, )) def setup(cursor): global CONFIG_PARSER # This module is often called, keep this object alive. CONFIG_PARSER = ConfigParser.RawConfigParser() CONFIG_PARSER.readfp(open(CONFIG_FILE)) agid.register(getring, setup)
from wazo_agid import agid logger = logging.getLogger(__name__) def fwdundoall(agi, cursor, args): user_id = _get_id_of_calling_user(agi) _user_disable_all_forwards(agi, user_id) def _get_id_of_calling_user(agi): return int(agi.get_variable('XIVO_USERID')) def _user_disable_all_forwards(agi, user_id): try: confd_client = agi.config['confd']['client'] disabled = {'enabled': False} body = { 'busy': disabled, 'noanswer': disabled, 'unconditional': disabled } confd_client.users(user_id).update_forwards(body) except Exception as e: logger.error('Error during disabling all forwards: %s', e) agid.register(fwdundoall)