log.rb 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. module Cti
  2. class Log < ApplicationModel
  3. self.table_name = 'cti_logs'
  4. store :preferences
  5. after_create :push_event, :push_caller_list
  6. after_update :push_event, :push_caller_list
  7. after_destroy :push_event, :push_caller_list
  8. =begin
  9. Cti::Log.create(
  10. direction: 'in',
  11. from: '007',
  12. from_comment: 'AAA',
  13. to: '008',
  14. to_comment: 'BBB',
  15. call_id: '1',
  16. comment: '',
  17. state: 'newCall',
  18. )
  19. Cti::Log.create(
  20. direction: 'in',
  21. from: '007',
  22. from_comment: '',
  23. to: '008',
  24. to_comment: '',
  25. call_id: '2',
  26. comment: '',
  27. state: 'answer',
  28. )
  29. Cti::Log.create(
  30. direction: 'in',
  31. from: '009',
  32. from_comment: '',
  33. to: '010',
  34. to_comment: '',
  35. call_id: '3',
  36. comment: '',
  37. state: 'hangup',
  38. )
  39. example data, can be used for demo
  40. Cti::Log.create(
  41. direction: 'in',
  42. from: '4930609854180',
  43. from_comment: 'Franz Bauer',
  44. to: '4930609811111',
  45. to_comment: 'Bob Smith',
  46. call_id: '00001',
  47. comment: '',
  48. state: 'newCall',
  49. done: false,
  50. preferences: {
  51. from: [
  52. {
  53. caller_id: '4930726128135',
  54. comment: nil,
  55. level: 'known',
  56. object: 'User',
  57. o_id: 2,
  58. user_id: 2,
  59. }
  60. ]
  61. }
  62. )
  63. Cti::Log.create(
  64. direction: 'out',
  65. from: '4930609854180',
  66. from_comment: 'Franz Bauer',
  67. to: '4930609811111',
  68. to_comment: 'Bob Smith',
  69. call_id: '00002',
  70. comment: '',
  71. state: 'newCall',
  72. preferences: {
  73. to: [
  74. {
  75. caller_id: '4930726128135',
  76. comment: nil,
  77. level: 'known',
  78. object: 'User',
  79. o_id: 2,
  80. user_id: 2,
  81. }
  82. ]
  83. }
  84. )
  85. Cti::Log.create(
  86. direction: 'in',
  87. from: '4930609854180',
  88. from_comment: 'Franz Bauer',
  89. to: '4930609811111',
  90. to_comment: 'Bob Smith',
  91. call_id: '00003',
  92. comment: '',
  93. state: 'answer',
  94. preferences: {
  95. from: [
  96. {
  97. caller_id: '4930726128135',
  98. comment: nil,
  99. level: 'known',
  100. object: 'User',
  101. o_id: 2,
  102. user_id: 2,
  103. }
  104. ]
  105. }
  106. )
  107. Cti::Log.create(
  108. direction: 'in',
  109. from: '4930609854180',
  110. from_comment: 'Franz Bauer',
  111. to: '4930609811111',
  112. to_comment: 'Bob Smith',
  113. call_id: '00004',
  114. comment: '',
  115. state: 'hangup',
  116. comment: 'normalClearing',
  117. done: false,
  118. preferences: {
  119. from: [
  120. {
  121. caller_id: '4930726128135',
  122. comment: nil,
  123. level: 'known',
  124. object: 'User',
  125. o_id: 2,
  126. user_id: 2,
  127. }
  128. ]
  129. }
  130. )
  131. Cti::Log.create(
  132. direction: 'in',
  133. from: '4930609854180',
  134. from_comment: 'Franz Bauer',
  135. to: '4930609811111',
  136. to_comment: 'Bob Smith',
  137. call_id: '00005',
  138. comment: '',
  139. state: 'hangup',
  140. start: Time.zone.now - 15.seconds,
  141. 'end': Time.zone.now,
  142. preferences: {
  143. from: [
  144. {
  145. caller_id: '4930726128135',
  146. comment: nil,
  147. level: 'known',
  148. object: 'User',
  149. o_id: 2,
  150. user_id: 2,
  151. }
  152. ]
  153. }
  154. )
  155. Cti::Log.create(
  156. direction: 'in',
  157. from: '4930609854180',
  158. from_comment: 'Franz Bauer',
  159. to: '4930609811111',
  160. to_comment: '',
  161. call_id: '00006',
  162. comment: '',
  163. state: 'hangup',
  164. start: Time.zone.now - 15.seconds,
  165. 'end': Time.zone.now,
  166. preferences: {
  167. from: [
  168. {
  169. caller_id: '4930726128135',
  170. comment: nil,
  171. level: 'known',
  172. object: 'User',
  173. o_id: 2,
  174. user_id: 2,
  175. }
  176. ]
  177. }
  178. )
  179. Cti::Log.create(
  180. direction: 'in',
  181. from: '4930609854180',
  182. from_comment: 'Franz Bauer',
  183. to: '4930609811111',
  184. to_comment: 'Bob Smith',
  185. call_id: '00007',
  186. comment: '',
  187. state: 'hangup',
  188. start: Time.zone.now - 15.seconds,
  189. 'end': Time.zone.now,
  190. preferences: {
  191. from: [
  192. {
  193. caller_id: '4930726128135',
  194. comment: nil,
  195. level: 'maybe',
  196. object: 'User',
  197. o_id: 2,
  198. user_id: 2,
  199. }
  200. ]
  201. }
  202. )
  203. Cti::Log.create(
  204. direction: 'in',
  205. from: '4930609854180',
  206. to: '4930609811112',
  207. call_id: '00008',
  208. comment: '',
  209. state: 'hangup',
  210. start: Time.zone.now - 20.seconds,
  211. 'end': Time.zone.now,
  212. preferences: {}
  213. )
  214. =end
  215. =begin
  216. Cti::Log.log
  217. returns
  218. {
  219. list: [...]
  220. assets: {...}
  221. }
  222. =end
  223. def self.log
  224. list = Cti::Log.order('created_at DESC, id DESC').limit(60)
  225. # add assets
  226. assets = list.map(&:preferences)
  227. .map { |p| p.slice(:from, :to) }
  228. .map(&:values).flatten
  229. .map { |caller_id| caller_id[:user_id] }.compact
  230. .map { |user_id| User.lookup(id: user_id) }.compact
  231. .each.with_object({}) { |user, a| user.assets(a) }
  232. {
  233. list: list,
  234. assets: assets,
  235. }
  236. end
  237. =begin
  238. processes a incoming event
  239. Cti::Log.process(
  240. 'cause' => '',
  241. 'event' => 'newCall',
  242. 'user' => 'user 1',
  243. 'from' => '4912347114711',
  244. 'to' => '4930600000000',
  245. 'callId' => '4991155921769858278-1', # or call_id
  246. 'direction' => 'in',
  247. )
  248. =end
  249. def self.process(params)
  250. comment = params['cause']
  251. event = params['event']
  252. user = params['user']
  253. call_id = params['callId'] || params['call_id']
  254. if user.class == Array
  255. user = user.join(', ')
  256. end
  257. from_comment = nil
  258. to_comment = nil
  259. preferences = nil
  260. if params['direction'] == 'in'
  261. to_comment = user
  262. from_comment, preferences = CallerId.get_comment_preferences(params['from'], 'from')
  263. else
  264. from_comment = user
  265. to_comment, preferences = CallerId.get_comment_preferences(params['to'], 'to')
  266. end
  267. case event
  268. when 'newCall'
  269. create(
  270. direction: params['direction'],
  271. from: params['from'],
  272. from_comment: from_comment,
  273. to: params['to'],
  274. to_comment: to_comment,
  275. call_id: call_id,
  276. comment: comment,
  277. state: event,
  278. preferences: preferences,
  279. )
  280. when 'answer'
  281. log = find_by(call_id: call_id)
  282. raise "No such call_id #{call_id}" if !log
  283. log.state = 'answer'
  284. log.start = Time.zone.now
  285. if user
  286. log.to_comment = user
  287. end
  288. log.comment = comment
  289. log.save
  290. when 'hangup'
  291. log = find_by(call_id: call_id)
  292. raise "No such call_id #{call_id}" if !log
  293. if params['direction'] == 'in' && log.state == 'newCall'
  294. log.done = false
  295. end
  296. if params['direction'] == 'in' && log.to_comment == 'voicemail'
  297. log.done = false
  298. end
  299. log.state = 'hangup'
  300. log.end = Time.zone.now
  301. log.comment = comment
  302. log.save
  303. else
  304. raise ArgumentError, "Unknown event #{event.inspect}"
  305. end
  306. end
  307. def push_event
  308. users = User.with_permissions('cti.agent')
  309. users.each do |user|
  310. # send notify about event
  311. Sessions.send_to(
  312. user.id,
  313. {
  314. event: 'cti_event',
  315. data: self,
  316. },
  317. )
  318. end
  319. end
  320. def push_caller_list
  321. list = Cti::Log.log
  322. users = User.with_permissions('cti.agent')
  323. users.each do |user|
  324. # send notify on create/update/delete
  325. Sessions.send_to(
  326. user.id,
  327. {
  328. event: 'cti_list_push',
  329. data: list,
  330. },
  331. )
  332. end
  333. end
  334. =begin
  335. cleanup caller logs
  336. Cti::Log.cleanup
  337. optional you can put the max oldest chat entries as argument
  338. Cti::Log.cleanup(12.months)
  339. =end
  340. def self.cleanup(diff = 12.months)
  341. Cti::Log.where('created_at < ?', Time.zone.now - diff).delete_all
  342. true
  343. end
  344. # adds virtual attributes when rendering #to_json
  345. # see http://api.rubyonrails.org/classes/ActiveModel/Serialization.html
  346. def attributes
  347. virtual_attributes = {
  348. 'from_pretty' => from_pretty,
  349. 'to_pretty' => to_pretty,
  350. }
  351. super.merge(virtual_attributes)
  352. end
  353. def from_pretty
  354. parsed = TelephoneNumber.parse(from&.sub(/^\+?/, '+'))
  355. parsed.send(parsed.valid? ? :international_number : :original_number)
  356. end
  357. def to_pretty
  358. parsed = TelephoneNumber.parse(to&.sub(/^\+?/, '+'))
  359. parsed.send(parsed.valid? ? :international_number : :original_number)
  360. end
  361. end
  362. end