refactoring and better standardisation
This commit is contained in:
parent
61c8d5f620
commit
25634ad4be
|
@ -0,0 +1,99 @@
|
||||||
|
# Environment var definitions
|
||||||
|
ENV_URI='TCX_SITE_URI'
|
||||||
|
ENV_AUTH_USER='TCX_API_AUTH_USERNAME'
|
||||||
|
ENV_AUTH_PASS='TCX_API_AUTH_PASSWORD'
|
||||||
|
|
||||||
|
class APIError(Exception):
|
||||||
|
pass
|
||||||
|
class ValidationError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class Request:
|
||||||
|
from requests import ConnectionError, exceptions
|
||||||
|
def __init__(self, uri, verify):
|
||||||
|
from requests import Session
|
||||||
|
self.base="%s/api/{}" % uri
|
||||||
|
self.sess=Session()
|
||||||
|
self.sess.verify=verify
|
||||||
|
|
||||||
|
def get(self, api, params=None, expect=200):
|
||||||
|
try:
|
||||||
|
resp=self.sess.get(url=self.base.format(api), params=params)
|
||||||
|
assert (resp.status_code==expect)
|
||||||
|
except AssertionError:
|
||||||
|
raise APIError("Assertion error when handling API response; response code was %s, but expected response was %s" % (resp.status_code, expect))
|
||||||
|
except exceptions.SSLError as e:
|
||||||
|
raise APIError("TLS error returned when communicating; use tls_verify=False or check leaf certs: %s" % str(e))
|
||||||
|
except exceptions.BaseHTTPError as e:
|
||||||
|
raise APIError("HTTP error raised when communicating: %s" % str(e))
|
||||||
|
except ConnectionError as e:
|
||||||
|
raise APIError("ConnectionError raised when communicating: %s" % str(e))
|
||||||
|
return resp
|
||||||
|
|
||||||
|
def post(self, api, params, expect=200):
|
||||||
|
try:
|
||||||
|
resp=self.sess.post(url=self.base.format(api), json=params)
|
||||||
|
assert (resp.status_code==expect)
|
||||||
|
except AssertionError:
|
||||||
|
raise APIError("Assertion error when handling API response; response code was %s, but expected response was %s" % (resp.status_code, expect))
|
||||||
|
except exceptions.SSLError as e:
|
||||||
|
raise APIError("TLS error returned when communicating; use tls_verify=False or check leaf certs: %s" % str(e))
|
||||||
|
except exceptions.BaseHTTPError as e:
|
||||||
|
raise APIError("HTTP error raised when communicating: %s" % str(e))
|
||||||
|
except ConnectionError as e:
|
||||||
|
raise APIError("ConnectionError raised when communicating: %s" % str(e))
|
||||||
|
except Exception as e:
|
||||||
|
raise APIError("Other exception raised during API call: %s" % str(e))
|
||||||
|
return resp
|
||||||
|
|
||||||
|
class Extension(object):
|
||||||
|
def __init__(self, parent, params):
|
||||||
|
self.tcx=parent
|
||||||
|
self.params=params
|
||||||
|
self.load()
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
res=self.tcx.rq.get('ExtensionList')
|
||||||
|
self.timestamp=res.headers.get('date')
|
||||||
|
res=list(filter(lambda ext: ext['Number'] == self.params, res.json()['list']))
|
||||||
|
assert (len(res)>0), "No extension found for: %s" % self.params
|
||||||
|
assert (len(res)==1), "More than one extension found for %s" % self.params
|
||||||
|
res=res[0]
|
||||||
|
self.number=res['Number']
|
||||||
|
self.firstname=res['FirstName']
|
||||||
|
self.surname=res['LastName']
|
||||||
|
self.name="%s %s" % (self.firstname, self.surname)
|
||||||
|
self.dnd=res['DND']
|
||||||
|
self.status=res['CurrentProfile']
|
||||||
|
self.mail=res['Email']
|
||||||
|
self.cli=res['OutboundCallerId']
|
||||||
|
self.mobile=res['MobileNumber']
|
||||||
|
self.online=res['IsRegistered']
|
||||||
|
|
||||||
|
|
||||||
|
class Py3CX:
|
||||||
|
def __init__(self, uri=None, tls_verify=True):
|
||||||
|
from os import getenv
|
||||||
|
self.uri=uri if uri is not None and uri.startswith('http') else getenv(ENV_URI, None)
|
||||||
|
assert (self.uri is not None and self.uri.startswith('http')), "Please provide URI"
|
||||||
|
self.uname=getenv(ENV_AUTH_USER, None)
|
||||||
|
self.passw=getenv(ENV_AUTH_PASS, None)
|
||||||
|
self.rq=Request(uri=self.uri, verify=tls_verify)
|
||||||
|
|
||||||
|
def authenticate(self, username=None, password=None):
|
||||||
|
if username is not None and password is not None:
|
||||||
|
self.uname=username
|
||||||
|
self.passw=password
|
||||||
|
assert (self.uname is not None and self.passw is not None), "Authentication information needed"
|
||||||
|
self.rq.post('login', params={
|
||||||
|
'Username': self.uname,
|
||||||
|
'Password': self.passw})
|
||||||
|
|
||||||
|
@property
|
||||||
|
def authenticated(self):
|
||||||
|
try:
|
||||||
|
self.rq.get('CurrentUser')
|
||||||
|
except APIError:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
100
py3cx.py
100
py3cx.py
|
@ -1,100 +0,0 @@
|
||||||
class Py3CX:
|
|
||||||
class _ApiCallBuilder:
|
|
||||||
apibase='api'
|
|
||||||
uri='{}/{}/{}'
|
|
||||||
# TODO: check login URI component
|
|
||||||
login={
|
|
||||||
'uri':'',
|
|
||||||
'method':'POST',
|
|
||||||
'expect':200
|
|
||||||
}
|
|
||||||
# Returns current username, displayed initial(s), 3CX phone system version, current roles, email addresses and information about privileges and enabled features
|
|
||||||
CurrentUser={
|
|
||||||
'uri':'CurrentUser',
|
|
||||||
'method':'GET',
|
|
||||||
'expepct':200
|
|
||||||
}
|
|
||||||
# Returns a list of current calls, including active trunk where available
|
|
||||||
ActiveCalls={
|
|
||||||
'uri':'activeCalls',
|
|
||||||
'method':'GET',
|
|
||||||
'expepct':200
|
|
||||||
}
|
|
||||||
SystemStatus={
|
|
||||||
'uri':'SystemStatus',
|
|
||||||
'method':'GET',
|
|
||||||
'expepct':200
|
|
||||||
}
|
|
||||||
# Returns event log entries; optional ?count=INT argument to retrieve specific number of events
|
|
||||||
EventLog={
|
|
||||||
'uri':'{}/getEventLog'.format(SystemStatus['uri']),
|
|
||||||
'method':'GET',
|
|
||||||
'expect':200
|
|
||||||
}
|
|
||||||
# Returns bytes of recording space used and allocated by quota, also returns recording states.
|
|
||||||
SystemStatusAdditional={
|
|
||||||
'uri':'{}/AdditionalStatus'.format(SystemStatus['uri']),
|
|
||||||
'method':'GET',
|
|
||||||
'expect':200
|
|
||||||
}
|
|
||||||
# Returns state of system health (whether firewall, configured trunks and phones meet 3CX support baselines)
|
|
||||||
SystemStatusHealth={
|
|
||||||
'uri':'{}/GetSingleStatus'.format(SystemStatus['uri']),
|
|
||||||
'method':'GET',
|
|
||||||
'expect':200
|
|
||||||
}
|
|
||||||
# TODO: API call 'SystemStatus/getDbInformation'
|
|
||||||
# TODO: API call 'TrunkList'
|
|
||||||
# TODO: API call 'InboundRulesList'
|
|
||||||
# TODO: API call 'OutboundRuleList'
|
|
||||||
# TODO: API call 'ActivityLog'
|
|
||||||
# TODO: API call 'ActivityLog/getKeepDays'
|
|
||||||
# TODO: API call 'ActivityLog/getKeepLogs'
|
|
||||||
# TODO: API call 'ActivityLog/getLogLevel'
|
|
||||||
# TODO: API call 'BackupAndRestoreList'
|
|
||||||
# TODO: API call 'CallLog'
|
|
||||||
# TODO: API call 'capture/getInterfaces'
|
|
||||||
# TODO: API call 'CustomParametersList'
|
|
||||||
# TODO: API call 'ExtensionList'
|
|
||||||
# TODO: API call 'GroupList'
|
|
||||||
# TODO: API call 'IpBlackList'
|
|
||||||
# TODO: API call 'IVRList'
|
|
||||||
# TODO: API call 'License'
|
|
||||||
# TODO: API call 'NumberBlackList'
|
|
||||||
# TODO: API call 'NumberBlackList/new' POST (followed by calls to 'edit/update' and 'edit/save')
|
|
||||||
# TODO: API call 'NumberBlackList/delete' POST {Ids: ["(number)"]}
|
|
||||||
# TODO: API call 'PhoneList'
|
|
||||||
# TODO: API call 'QueueList'
|
|
||||||
# TODO: API call 'RecordingList'
|
|
||||||
# TODO: API call 'RingGroupList'
|
|
||||||
# TODO: API call 'SystemPromptList'
|
|
||||||
# TODO: API call 'SystemPromptList/promptSets'
|
|
||||||
# TODO: API call 'SystemPromptList/promptSetUpdates'
|
|
||||||
# TODO: API call 'UpdateChecker/GetFromParams'
|
|
||||||
# TODO: API call 'updateChecker/check' POST
|
|
||||||
# TODO: API call 'updateChecker/isDebian8'
|
|
||||||
# TODO: API call 'crm/serverCrmUpdates'
|
|
||||||
# TODO: API call 'crm/clientCrmUpdates'
|
|
||||||
# TODO: API call 'CrmList/CrmSettings' POST
|
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, uri=None, account=None):
|
|
||||||
from os import getenv
|
|
||||||
if uri==None:
|
|
||||||
uri=getenv('TCX_URI', None)
|
|
||||||
if account==None:
|
|
||||||
account={
|
|
||||||
"username": getenv('TCX_USERNAME', None),
|
|
||||||
"password": getenv('TCX_PASSWORD', None)
|
|
||||||
}
|
|
||||||
assert (len(account['username']>1)), "py3cx was initialised without account information, and TCX_USERNAME does not contain a valid username."
|
|
||||||
assert (len(account['password']>5)), "py3cx was initialised without account information, and TCX_PASSWORD does not contain a valid password."
|
|
||||||
#Validation for initialisation parameters
|
|
||||||
assert (len(uri)>0), "uri must be a full URI to your target 3CX server"
|
|
||||||
assert (uri.startswith('http')), "uri must be a valid HTTP or HTTPS URI"
|
|
||||||
assert ('username' in account), "account object must contain username property"
|
|
||||||
assert ('password' in account), "account object must contain password property"
|
|
||||||
assert (len(account['username'])>1), "account object must contain a valid username"
|
|
||||||
assert (len(account['password'])>5), "account object must contain a valid password"
|
|
||||||
self._base=uri
|
|
||||||
self._account=account
|
|
|
@ -0,0 +1 @@
|
||||||
|
requests
|
Loading…
Reference in New Issue