utils.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #!/usr/bin/env python3
  2. from dataclasses import dataclass, asdict
  3. from panoramisk import Message
  4. from datetime import datetime as dt
  5. from datetime import timedelta as td
  6. TRUEs = ('true', '1', 'y', 'yes')
  7. NONEs = (None,'none','')
  8. externalContexts = ('from-trunk',
  9. 'from-digital',
  10. 'from-pstn',
  11. 'from-did-direct')
  12. # userstate presencestate maping:
  13. _ustates = ['idle', 'inuse', 'busy', 'unavailable', 'ringing', 'inuse&ringing','hold', 'inuse&hold'] #presence:
  14. _states = [['available', 'busy', 'busy', 'unavailable', 'ringing', 'busy', 'busy', 'busy'], #not_set
  15. ['unavailable', 'busy', 'busy', 'unavailable', 'ringing', 'busy', 'busy', 'busy'], #unavailable
  16. ['available', 'busy', 'busy', 'unavailable', 'ringing', 'busy', 'busy', 'busy'], #available
  17. ['away', 'busy', 'busy', 'unavailable', 'ringing', 'busy', 'busy', 'busy'], #away
  18. ['available', 'busy', 'busy', 'unavailable', 'ringing', 'busy', 'busy', 'busy'], #xa
  19. ['available', 'busy', 'busy', 'unavailable', 'ringing', 'busy', 'busy', 'busy'], #chat
  20. ['dnd', 'busy', 'busy', 'unavailable', 'ringing', 'busy', 'busy', 'busy']] #dnd
  21. _pstates = ['not_set',
  22. 'unavailable',
  23. 'available',
  24. 'away',
  25. 'xa',
  26. 'chat',
  27. 'dnd']
  28. # combinedStates[userstate][presencestate]=combinedState
  29. combinedStates = {_u: {_p: _states[_pstates.index(_p)][_ustates.index(_u)] for _p in _pstates} for _u in _ustates}
  30. presenceStates = _pstates
  31. NO_AUTH_ROUTES = ('/ui','/openapi.json','/favicon.ico')
  32. SWAGGER_JS_URL = "https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/3.37.2/swagger-ui-bundle.js"
  33. SWAGGER_CSS_URL = "https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/3.37.2/swagger-ui.min.css"
  34. SWAGGER_TEMPLATE = '''
  35. <head>
  36. <link type="text/css" rel="stylesheet" href="{{ css_url }}">
  37. <title>{{ title }}</title>
  38. </head>
  39. <body>
  40. <div id="swagger-ui"></div>
  41. <script src="{{ js_url }}"></script>
  42. <script>
  43. const ui = SwaggerUIBundle({
  44. deepLinking: true,
  45. dom_id: "#swagger-ui",
  46. layout: "BaseLayout",
  47. presets: [
  48. SwaggerUIBundle.presets.apis,
  49. SwaggerUIBundle.SwaggerUIStandalonePreset
  50. ],
  51. showExtensions: true,
  52. showCommonExtensions: true,
  53. url: "/openapi.json"
  54. });
  55. </script>
  56. </body>'''
  57. def parseDatetime(dateString):
  58. _dt = None
  59. if dateString is not None:
  60. try:
  61. _dt = dt.strptime(dateString, '%Y%m%d%H%M%S')
  62. except ValueError:
  63. pass
  64. if _dt is None:
  65. try:
  66. _dt = dt.fromtimestamp(int(dateString))
  67. except ValueError:
  68. pass
  69. if _dt is None:
  70. try:
  71. _dt = dt.fromisoformat(dateString)
  72. except ValueError:
  73. pass
  74. return _dt
  75. def freepbxExternalContext(context):
  76. if ((context in externalContexts) or
  77. (context.startswith('from-trunk-')) or
  78. (context.startswith('from-did-')) or
  79. (context.startswith('ivr-'))):
  80. return True
  81. return False
  82. def followMe2DevState(followMeState):
  83. if followMeState == 'DIRECT':
  84. return 'INUSE'
  85. if followMeState == 'EXTENSION':
  86. return 'NOT_INUSE'
  87. return 'INVALID'
  88. @dataclass
  89. class QueueMember:
  90. user: str
  91. name: str = ''
  92. location: str = ''
  93. membership: str = ''
  94. stateinterface: str = ''
  95. status: str = ''
  96. def fromMessage(self, _m: Message):
  97. for key in asdict(self).keys():
  98. if key in _m:
  99. setattr(self, key, _m[key])
  100. return self
  101. @dataclass
  102. class GlobalVars:
  103. FMDEVSTATE: str = ''
  104. QUEDEVSTATE: str = ''
  105. QUEUETOGGLE: str = ''
  106. QUEUEPAUSETOGGLE: str = ''
  107. INTERCOMCODE: str = ''
  108. CAMPONTOGGLE: str = ''
  109. DNDDEVSTATE: str = ''
  110. CFDEVSTATE: str = ''
  111. def d(self):
  112. return asdict(self)
  113. def jsonAPIReply(status='success', data=None, message=None):
  114. return {'status':status, 'data': data, 'message': message}
  115. def errorReply(message=None):
  116. return jsonAPIReply(status='error', data=None, message=message)
  117. def successReply(data=None,message=None):
  118. return jsonAPIReply(status='success', data=data, message=message)
  119. def noUser(user):
  120. return errorReply('User {} does not exist'.format(user))
  121. def noDevice(device):
  122. return errorReply('Device {} does not exist'.format(device))
  123. def noUserDevice(user):
  124. return errorReply('User {} does not exist or is not bound to device'.format(user))
  125. def noUserChannel(user):
  126. return errorReply('User {} does not have active calls'.format(user))
  127. def stateCacheEmpty():
  128. return errorReply('Users states cache update failed')
  129. def invalidState(state):
  130. return errorReply('Invalid state "{}" provided'.format(state))
  131. def alreadyBound(user, device):
  132. return errorReply('User {} is already bound to device {}'.format(user, device))
  133. def bindError(user, device):
  134. return errorReply('Failed binding user {} to device {}'.format(user, device))
  135. def hintError(user, device):
  136. return errorReply('Failed setting hint for user {} on device {}'.format(user, device))
  137. def noUserBound(device):
  138. return errorReply('No user is bound to device {}'.format(device))
  139. def successfullyTransfered(userA, userB):
  140. return successReply({'userA':userA,'userB':userB},
  141. 'Call was successfully transfered from user {} to user {}'.format(userA, userB))
  142. def successfullyBound(user, device):
  143. return successReply({'user':user,'device':device},
  144. 'User {} is successfully bound to device {}'.format(user, device))
  145. def successfullyUnbound(user, device):
  146. return successReply({'user':user,'device':device},
  147. 'User {} was successfully unbound from device {}'.format(user, device))
  148. def successfullySetState(user, state):
  149. return successReply({'user':user,'state':state},
  150. 'State "{}" was successfully set for user {}'.format(state, user))