Source code for five9.five9

# -*- coding: utf-8 -*-
# Copyright 2017-TODAY LasLabs Inc.
# License MIT (https://opensource.org/licenses/MIT).

import requests
import zeep

from collections import OrderedDict

try:
    from urllib.parse import quote
except ImportError:
    from urllib import quote

from .environment import Environment


[docs]class Five9(object): WSDL_CONFIGURATION = 'https://api.five9.com/wsadmin/v9_5/' \ 'AdminWebService?wsdl&user=%s' WSDL_SUPERVISOR = 'https://api.five9.com/wssupervisor/v9_5/' \ 'SupervisorWebService?wsdl&user=%s' # These attributes are used to create the supervisor session. force_logout_session = True rolling_period = 'Minutes30' statistics_range = 'CurrentWeek' shift_start_hour = 8 time_zone_offset = -7 # API Objects _api_configuration = None _api_supervisor = None _api_supervisor_session = None @property def configuration(self): """Return an authenticated connection for use, open new if required. Returns: AdminWebService: New or existing session with the Five9 Admin Web Services API. """ return self._cached_client('configuration') @property def supervisor(self): """Return an authenticated connection for use, open new if required. Returns: SupervisorWebService: New or existing session with the Five9 Statistics API. """ supervisor = self._cached_client('supervisor') if not self._api_supervisor_session: self._api_supervisor_session = self.__create_supervisor_session( supervisor, ) return supervisor def __init__(self, username, password): self.username = username self.auth = requests.auth.HTTPBasicAuth(username, password) self.env = Environment(self)
[docs] @staticmethod def create_mapping(record, keys): """Create a field mapping for use in API updates and creates. Args: record (BaseModel): Record that should be mapped. keys (list[str]): Fields that should be mapped as keys. Returns: dict: Dictionary with keys: * ``field_mappings``: Field mappings as required by API. * ``data``: Ordered data dictionary for input record. """ ordered = OrderedDict() field_mappings = [] for key, value in record.items(): ordered[key] = value field_mappings.append({ 'columnNumber': len(ordered), # Five9 is not zero indexed. 'fieldName': key, 'key': key in keys, }) return { 'field_mappings': field_mappings, 'data': ordered, 'fields': list(ordered.values()), }
[docs] @staticmethod def parse_response(fields, records): """Parse an API response into usable objects. Args: fields (list[str]): List of strings indicating the fields that are represented in the records, in the order presented in the records.:: [ 'number1', 'number2', 'number3', 'first_name', 'last_name', 'company', 'street', 'city', 'state', 'zip', ] records (list[dict]): A really crappy data structure representing records as returned by Five9:: [ { 'values': { 'data': [ '8881234567', None, None, 'Dave', 'Lasley', 'LasLabs Inc', None, 'Las Vegas', 'NV', '89123', ] } } ] Returns: list[dict]: List of parsed records. """ data = [i['values']['data'] for i in records] return [ {fields[idx]: row for idx, row in enumerate(d)} for d in data ]
[docs] @classmethod def create_criteria(cls, query): """Return a criteria from a dictionary containing a query. Query should be a dictionary, keyed by field name. If the value is a list, it will be divided into multiple criteria as required. """ criteria = [] for name, value in query.items(): if isinstance(value, list): for inner_value in value: criteria += cls.create_criteria({name: inner_value}) else: criteria.append({ 'criteria': { 'field': name, 'value': value, }, }) return criteria or None
def _get_authenticated_client(self, wsdl): """Return an authenticated SOAP client. Returns: zeep.Client: Authenticated API client. """ return zeep.Client( wsdl % quote(self.username), transport=zeep.Transport( session=self._get_authenticated_session(), ), ) def _get_authenticated_session(self): """Return an authenticated requests session. Returns: requests.Session: Authenticated session for use. """ session = requests.Session() session.auth = self.auth return session def _cached_client(self, client_type): attribute = '_api_%s' % client_type if not getattr(self, attribute, None): wsdl = getattr(self, 'WSDL_%s' % client_type.upper()) client = self._get_authenticated_client(wsdl) setattr(self, attribute, client) return getattr(self, attribute).service def __create_supervisor_session(self, supervisor): """Create a new session on the supervisor service. This is required in order to use most methods for the supervisor, so it is called implicitly when generating a supervisor session. """ session_params = { 'forceLogoutSession': self.force_logout_session, 'rollingPeriod': self.rolling_period, 'statisticsRange': self.statistics_range, 'shiftStart': self.__to_milliseconds( self.shift_start_hour, ), 'timeZone': self.__to_milliseconds( self.time_zone_offset, ), } supervisor.setSessionParameters(session_params) return session_params @staticmethod def __to_milliseconds(hour): return hour * 60 * 60 * 1000