cache.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. #!/usr/bin/env python3
  2. # encoding:utf-8
  3. import json
  4. import sys
  5. import time
  6. import traceback
  7. import uuid
  8. from datetime import datetime
  9. from src.core import singleton_keys
  10. from src.core.callcenter.constant import *
  11. from src.core.callcenter.api import AgentInfo, CallInfo, RouteGateway
  12. from src.core.callcenter.dao import Agent, Phone
  13. from src.core.callcenter.data_handler import DataHandleServer
  14. from src.core.datasource import RedisHandler
  15. from cacheout import CacheManager
  16. @singleton_keys
  17. class Cache:
  18. def __init__(self, app):
  19. self.cacheDay = 7
  20. # self.deviceCall = {}
  21. # self.deviceUserPart = {}
  22. self.logger = app.logger
  23. self.redis_handler = RedisHandler()
  24. self.dataHandleServer = DataHandleServer(app)
  25. self.cacheman = CacheManager({'call':{'maxsize': 600, 'ttl': 60*60*1},
  26. 'agent': {'maxsize': 600, 'ttl': 60*60*1},
  27. 'deviceCall': {'maxsize': 600, 'ttl': 60*60*1},
  28. 'deviceUserPart': {'maxsize': 600, 'ttl': 60*60*1},
  29. })
  30. def get_agent_info(self, saas_id, agent_number):
  31. key = AGENT_INFO + saas_id + ":" + agent_number
  32. agent_info = self.cacheman['agent'].get(key)
  33. if agent_info:
  34. return agent_info
  35. text = self.redis_handler.get(key)
  36. self.logger.info('get_agent_info %s %s %s'%(saas_id, agent_number, text))
  37. if text:
  38. agent_info = AgentInfo.from_json(text)
  39. self.cacheman['agent'].set(key, agent_info)
  40. return agent_info
  41. phone = self.dataHandleServer.get_agent_phone(saas_id, agent_number)
  42. agent_info = AgentInfo(saas_id=saas_id, sip_server=phone.sip_server, agent_number=agent_number)
  43. self.logger.info('get_agent_info %s %s %s'% (saas_id, agent_number, agent_info))
  44. self.add_agent_info(agent=agent_info)
  45. return agent_info
  46. def refresh_agent_token(self, agent_number, token):
  47. self.redis_handler.set(AGENT_TOKEN + token, agent_number, self.cacheDay * 24 * 60 * 60)
  48. def delete_key(self, key):
  49. self.redis_handler.redis.delete(key)
  50. def get_agent_number(self, token):
  51. return self.redis_handler.get(AGENT_TOKEN + token)
  52. # 缓存坐席
  53. def add_agent_info(self, call_info: CallInfo = None, agent: AgentInfo = None, call_id=None, device_id=None):
  54. if call_info and not agent:
  55. agent = self.get_agent_info(call_info.saas_id, call_info.agent_key)
  56. if not agent:
  57. return
  58. if call_id:
  59. agent.call_id = call_id
  60. if device_id:
  61. agent.device_id = device_id
  62. key = AGENT_INFO + agent.saas_id + ":" + agent.agent_number
  63. self.cacheman['agent'].set(key, agent)
  64. self.redis_handler.set(key, agent.to_json_string(), self.cacheDay * 24 * 60 * 60)
  65. # 缓存CALL_INFO
  66. def add_call_info(self, call: CallInfo, persistent=True):
  67. for k, v in call.device_info_map.items():
  68. self.add_device(k, call.call_id)
  69. # print('add_call_info call_id:%s, call=%s'% (call.call_id, call))
  70. self.cacheman['call'].set(call.call_id, call)
  71. if persistent:
  72. self.redis_handler.set(CALL_INFO + call.call_id, call.to_json_string(), self.cacheDay * 24 * 60 * 60)
  73. def get_call_id_by_device_id(self, device_id):
  74. return self.cacheman['deviceCall'].get(device_id)
  75. # call_id = self.deviceCall.get(device_id)
  76. # return call_id
  77. # 获取callInfo
  78. def get_call_info(self, call_id):
  79. if not call_id:
  80. return None
  81. call_info = self.cacheman['call'].get(call_id)
  82. if call_info:
  83. return call_info
  84. text = self.redis_handler.get(CALL_INFO + call_id)
  85. if text:
  86. call_info = CallInfo.from_json(text)
  87. self.cacheman['call'].set(call_id, call_info)
  88. return call_info
  89. # print('get_call_info call_id:%s, text:%s'% (call_id, text))
  90. def remove_call_info(self, call_id):
  91. if not call_id:
  92. return None
  93. call_info = self.get_call_info(call_id)
  94. if call_info and call_info.device_info_map:
  95. for k, v in call_info.device_info_map.items():
  96. self.cacheman['deviceCall'].delete(k)
  97. # self.deviceCall.pop(k)
  98. self.cacheman['call'].delete(call_id)
  99. self.delete_key(CALL_INFO + call_id)
  100. def add_device(self, device_id, call_id):
  101. if not device_id or not call_id:
  102. return None
  103. self.cacheman['deviceCall'].set(device_id, call_id)
  104. # self.deviceCall[device_id] = call_id
  105. def get_user_part(self, device_id):
  106. return self.cacheman['deviceUserPart'].get(device_id)
  107. # return self.deviceUserPart.get(device_id)
  108. def add_device_user_part(self, device_id, user_part):
  109. if not device_id or not user_part:
  110. return
  111. self.cacheman['deviceUserPart'].set(device_id, user_part)
  112. # self.deviceUserPart[device_id] = user_part
  113. def get_route_gateway(self, saas_id):
  114. return RouteGateway(id=1,
  115. saas_id=saas_id,
  116. name='8247190',
  117. media_host='192.168.120.162',
  118. media_port=5060,
  119. caller_prefix='',
  120. called_prefix='',
  121. status=0)
  122. def add_delay_message(self, action, delay_action, timeouts):
  123. delay_action.uuid = str(uuid.uuid4())
  124. key = CTI_ENGINE_DELAY_ACTION % action
  125. msg = delay_action.to_json_string()
  126. action_time = datetime.now().timestamp()*1000 + timeouts * 1000
  127. self.redis_handler.redis.zadd(key, {msg : action_time})
  128. def get_delay_message(self, action):
  129. key = CTI_ENGINE_DELAY_ACTION % action
  130. current_time = int(datetime.now().timestamp() * 1000) # 毫秒级时间戳
  131. members = self.redis_handler.redis.zrangebyscore(key, 0, current_time, start=0, num=DELAY_ACTION_BATCH_SIZE, withscores=True)
  132. if not members:
  133. return []
  134. self.logger.info('get_delay_message %s %s %s'%(key, action, members))
  135. # scored_entries = [{"member": entry[0].decode('utf-8'), "score": entry[1]} for entry in members]
  136. action_list = [entry[0].decode('utf-8') for entry in members]
  137. self.logger.info('get_delay_message %s %s %s'%(key, action, json.dumps(action_list)))
  138. if action_list:
  139. a = self.redis_handler.redis.zrem(key, *action_list)
  140. self.logger.info('get_delay_message %s %s %s %s'%(key, action, json.dumps(action_list), a))
  141. return action_list
  142. def lock_delay_action(self, val):
  143. key = CTI_ENGINE_DELAY_ACTION_LOCK % val
  144. return self.redis_handler.redis.set(key, "1", ex=60*10, nx=True)
  145. def set_need_play_hold_music(self, call_id):
  146. key = NEED_PLAY_HOLD_MUSIC % call_id
  147. return self.redis_handler.redis.set(key, "1", ex=60 * 1, nx=True)
  148. def get_need_play_hold_music(self, call_id):
  149. key = NEED_PLAY_HOLD_MUSIC % call_id
  150. return self.redis_handler.redis.get(key)
  151. def del_need_play_hold_music(self, call_id):
  152. key = NEED_PLAY_HOLD_MUSIC % call_id
  153. self.delete_key(key)
  154. def set_after_play_hold_music(self, call_id):
  155. key = AFTER_PLAY_HOLD_MUSIC % call_id
  156. return self.redis_handler.redis.set(key, "1", ex=60 * 1, nx=True)
  157. def get_after_play_hold_music(self, call_id):
  158. key = AFTER_PLAY_HOLD_MUSIC % call_id
  159. return self.redis_handler.redis.get(key)
  160. def get_call_is_end(self, call_id):
  161. key = CTI_MANAGE_CENTER_CALL_END_KEY % call_id
  162. return self.redis_handler.get(key)
  163. def set_call_is_end(self, call_id):
  164. key = CTI_MANAGE_CENTER_CALL_END_KEY % call_id
  165. return self.redis_handler.redis.set(key, "1", ex=60 * 10, nx=True)
  166. def get_call_is_answer(self, saas_id, flow_id):
  167. key = CTI_AGENT_MANUAL_ANSWER%(saas_id, flow_id)
  168. return self.redis_handler.get(key)
  169. def set_call_is_answer(self, saas_id, flow_id):
  170. key = CTI_AGENT_MANUAL_ANSWER%(saas_id, flow_id)
  171. return self.redis_handler.redis.set(key, "1", ex=60, nx=True)
  172. def lock_register_per_hours(self):
  173. hour = datetime.now().strftime('%Y%m%d')
  174. key = BOT_REGISTER_PER_HOURS %hour
  175. return self.redis_handler.redis.get(key)
  176. def set_register_per_hours(self, expire=86400):
  177. hour = datetime.now().strftime('%Y%m%d')
  178. key = BOT_REGISTER_PER_HOURS %hour
  179. return self.redis_handler.redis.set(key, "1", ex=expire, nx=True)
  180. def get_pjsua_thread_lock(self):
  181. minute = datetime.now().strftime('%Y%m%d%H%M')
  182. key = BOT_PJSUA_THREAD_LOCK % minute
  183. _lock = self.redis_handler.redis.get(key)
  184. # self.logger.info("get_pjsua_thread_lock %s", _lock)
  185. return _lock
  186. def del_pjsua_thread_lock(self):
  187. minute = datetime.now().strftime('%Y%m%d%H%M')
  188. key = BOT_PJSUA_THREAD_LOCK % minute
  189. return self.redis_handler.redis.delete(key)
  190. def set_pjsua_thread_lock(self, expire=60*3):
  191. minute = datetime.now().strftime('%Y%m%d%H%M')
  192. key = BOT_PJSUA_THREAD_LOCK % minute
  193. self.logger.info("set_pjsua_thread_lock")
  194. return self.redis_handler.redis.set(key, "1", ex=expire, nx=True)
  195. def get_serial_no_answer_cnt(self, call_info:CallInfo):
  196. try:
  197. if call_info.hangup_count >= call_info.answer_count:
  198. key = CALL_SERIAL_NO_ANSWER % SAAS_ID
  199. self.logger.info('get_serial_no_answer_cnt:call_id=%s, call_time_length=%s', call_info.call_id, call_info.answer_count)
  200. if call_info.answer_count <= 0:
  201. self.redis_handler.redis.sadd(key, call_info.call_id)
  202. return self.redis_handler.redis.scard(key)
  203. else:
  204. self.redis_handler.redis.delete(key)
  205. except Exception as e:
  206. traceback.print_exc()
  207. self.logger.info('get_serial_no_answer_cnt:exception, msg:%s',e )
  208. return 0
  209. def get_serial_speed_hangup_cnt(self, call_info:CallInfo):
  210. try:
  211. if call_info.hangup_count >= call_info.answer_count:
  212. now = datetime.now().timestamp()
  213. key = CALL_SERIAL_SPEED_HANGUP % SAAS_ID
  214. call_len = now - call_info.call_time
  215. self.logger.info('get_serial_speed_hangup_cnt:call_id=%s, call_time_length=%s', call_info.call_id, call_len)
  216. if call_len <= CALL_SERIAL_SPEED_HANGUP_OFFSET:
  217. self.redis_handler.redis.sadd(key, call_info.call_id)
  218. return self.redis_handler.redis.scard(key)
  219. else:
  220. self.redis_handler.redis.delete(key)
  221. except Exception as e:
  222. traceback.print_exc()
  223. self.logger.info('get_serial_speed_hangup_cnt:exception, msg:%s',e)
  224. return 0