WebMessageObject.swift 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748
  1. // _____ _
  2. // |_ _| |_ _ _ ___ ___ _ __ __ _
  3. // | | | ' \| '_/ -_) -_) ' \/ _` |_
  4. // |_| |_||_|_| \___\___|_|_|_\__,_(_)
  5. //
  6. // Threema iOS Client
  7. // Copyright (c) 2018-2020 Threema GmbH
  8. //
  9. // This program is free software: you can redistribute it and/or modify
  10. // it under the terms of the GNU Affero General Public License, version 3,
  11. // as published by the Free Software Foundation.
  12. //
  13. // This program is distributed in the hope that it will be useful,
  14. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. // GNU Affero General Public License for more details.
  17. //
  18. // You should have received a copy of the GNU Affero General Public License
  19. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  20. import UIKit
  21. import ThreemaFramework
  22. class WebMessageObject: NSObject {
  23. var baseMessage: BaseMessage
  24. var type: String
  25. var id: String
  26. var body: String?
  27. var thumbnail: Dictionary<AnyHashable, Any>?
  28. var date: Int
  29. var events: [[String: Any]]?
  30. var sortKey: UInt64
  31. var partnerId: String?
  32. var isOutbox: Bool
  33. var isStatus: Bool = false
  34. var caption: String?
  35. var statusType: String?
  36. var unread: Bool?
  37. var state: String?
  38. var quote: Dictionary<AnyHashable, Any>?
  39. var file: Dictionary<AnyHashable, Any>?
  40. var video: Dictionary<AnyHashable, Any>?
  41. var audio: Dictionary<AnyHashable, Any>?
  42. var location: Dictionary<AnyHashable, Any>?
  43. var voip: Dictionary<AnyHashable, Any>?
  44. init(message:BaseMessage, conversation: Conversation, forConversationsRequest: Bool, session: WCSession) {
  45. baseMessage = message
  46. type = conversation.isGroup() ? "group" : "contact"
  47. id = message.id.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
  48. let currentDate = message.dateForCurrentState() ?? message.date
  49. date = Int((currentDate?.timeIntervalSince1970)!)
  50. let messageEvents = MessageEvents.init(baseMessage: baseMessage)
  51. events = messageEvents.events
  52. sortKey = UInt64((message.date.timeIntervalSince1970 * 1000.0).rounded())
  53. if message.sender != nil {
  54. if message.isOwn.boolValue {
  55. partnerId = MyIdentityStore.shared().identity
  56. } else {
  57. partnerId = message.sender.identity
  58. }
  59. }
  60. else if conversation.contact != nil {
  61. if message.isOwn.boolValue {
  62. partnerId = MyIdentityStore.shared().identity
  63. } else {
  64. partnerId = conversation.contact.identity
  65. }
  66. }
  67. isOutbox = message.isOwn.boolValue
  68. unread = !message.read.boolValue
  69. let messageState = message.messageState
  70. switch messageState {
  71. case MESSAGE_STATE_SENDING:
  72. state = "sending"
  73. break
  74. case MESSAGE_STATE_SENT:
  75. state = "sent"
  76. break
  77. case MESSAGE_STATE_DELIVERED:
  78. state = "delivered"
  79. break
  80. case MESSAGE_STATE_READ:
  81. state = "read"
  82. break
  83. case MESSAGE_STATE_USER_ACK:
  84. state = "user-ack"
  85. break
  86. case MESSAGE_STATE_USER_DECLINED:
  87. state = "user-dec"
  88. break
  89. case MESSAGE_STATE_FAILED:
  90. state = "send-failed"
  91. break
  92. default:
  93. state = nil
  94. }
  95. super.init()
  96. switch message {
  97. case is TextMessage:
  98. addTextMessage(message)
  99. case is ImageMessage:
  100. addImageMessage(message, forConversationsRequest: forConversationsRequest, session: session)
  101. case is VideoMessage:
  102. addVideoMessage(message, forConversationsRequest: forConversationsRequest, session: session)
  103. case is AudioMessage:
  104. addAudioMessage(message)
  105. case is LocationMessage:
  106. addLocationMessage(message)
  107. case is FileMessage:
  108. addFileMessage(message, forConversationsRequest: forConversationsRequest, session: session)
  109. case is SystemMessage:
  110. addSystemMessage(message)
  111. case is BallotMessage:
  112. addBallotMessage(message)
  113. default:
  114. break
  115. }
  116. }
  117. init(message:BaseMessage, conversation: Conversation) {
  118. baseMessage = message
  119. if conversation.isGroup() {
  120. type = "group"
  121. } else {
  122. type = "contact"
  123. }
  124. id = message.id.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
  125. var currentDate = message.dateForCurrentState()
  126. if currentDate == nil {
  127. currentDate = message.date
  128. }
  129. date = Int((currentDate?.timeIntervalSince1970)!)
  130. sortKey = UInt64((currentDate?.timeIntervalSince1970)!)
  131. isOutbox = message.isOwn.boolValue
  132. if message is SystemMessage {
  133. let systemMessage = message as! SystemMessage
  134. if !systemMessage.isCallType() {
  135. isStatus = true
  136. }
  137. }
  138. }
  139. func objectDict() -> [String: Any] {
  140. var objectDict:[String: Any] = ["type": type, "id": id, "date": date, "isOutbox": isOutbox, "isStatus": isStatus, "sortKey": sortKey]
  141. if events != nil {
  142. objectDict.updateValue(events!, forKey: "events")
  143. }
  144. if body != nil {
  145. objectDict.updateValue(body!, forKey: "body")
  146. }
  147. if thumbnail != nil {
  148. objectDict.updateValue(thumbnail!, forKey: "thumbnail")
  149. }
  150. if partnerId != nil {
  151. objectDict.updateValue(partnerId!, forKey: "partnerId")
  152. }
  153. if caption != nil {
  154. objectDict.updateValue(caption!, forKey: "caption")
  155. }
  156. if statusType != nil {
  157. objectDict.updateValue(statusType!, forKey: "statusType")
  158. }
  159. if unread != nil {
  160. objectDict.updateValue(unread!, forKey: "unread")
  161. }
  162. if state != nil {
  163. objectDict.updateValue(state!, forKey: "state")
  164. }
  165. if quote != nil {
  166. objectDict.updateValue(quote!, forKey: "quote")
  167. }
  168. if file != nil {
  169. objectDict.updateValue(file!, forKey: "file")
  170. }
  171. if video != nil {
  172. objectDict.updateValue(video!, forKey: "video")
  173. }
  174. if audio != nil {
  175. objectDict.updateValue(audio!, forKey: "audio")
  176. }
  177. if location != nil {
  178. objectDict.updateValue(location!, forKey: "location")
  179. }
  180. if voip != nil {
  181. objectDict.updateValue(voip!, forKey: "voip")
  182. }
  183. return objectDict
  184. }
  185. func removedObjectDict() -> [String: Any] {
  186. return ["type": type, "id": id, "date": date, "isOutbox": isOutbox, "isStatus": isStatus, "sortKey": sortKey]
  187. }
  188. private func addTextMessage(_ message: BaseMessage) {
  189. let textMessage = message as! TextMessage
  190. type = "text"
  191. body = textMessage.text
  192. thumbnail = nil
  193. caption = nil
  194. statusType = "text"
  195. var quotedIdentity: NSString?
  196. var remainingBody: NSString?
  197. let quotedText = QuoteParser.parseQuote(fromMessage: textMessage.text, quotedIdentity: &quotedIdentity, remainingBody: &remainingBody)
  198. if quotedText != nil {
  199. quote = ["identity": quotedIdentity!, "text": quotedText!]
  200. body = remainingBody as String?
  201. }
  202. }
  203. private func addImageMessage(_ message: BaseMessage, forConversationsRequest: Bool, session: WCSession) {
  204. let imageMessage = message as! ImageMessage
  205. type = "image"
  206. body = nil
  207. statusType = "text"
  208. if imageMessage.image == nil && imageMessage.thumbnail == nil {
  209. return
  210. }
  211. else if imageMessage.image == nil {
  212. if imageMessage.thumbnail.data == nil {
  213. return
  214. }
  215. }
  216. else if imageMessage.thumbnail == nil {
  217. if imageMessage.image.data == nil {
  218. return
  219. }
  220. }
  221. else if imageMessage.image.data == nil && imageMessage.thumbnail.data == nil {
  222. return
  223. }
  224. if !session.requestedThumbnails(contains: baseMessage.id) {
  225. let webThumbnail = WebThumbnail.init(imageMessage: imageMessage, onlyThumbnail: true)
  226. thumbnail = webThumbnail.objectDict()
  227. if !forConversationsRequest {
  228. session.addRequestedThumbnail(messageId: baseMessage.id)
  229. }
  230. }
  231. if let image = imageMessage.image, let imageCaption = image.getCaption() {
  232. caption = imageCaption
  233. }
  234. }
  235. private func addVideoMessage(_ message: BaseMessage, forConversationsRequest: Bool, session: WCSession) {
  236. let videoMessage = message as! VideoMessage
  237. type = "video"
  238. body = nil
  239. if (videoMessage.thumbnail != nil), !session.requestedThumbnails(contains: baseMessage.id) {
  240. let webThumbnail = WebThumbnail.init(videoMessage, onlyThumbnail: true)
  241. thumbnail = webThumbnail.objectDict()
  242. if !forConversationsRequest {
  243. session.addRequestedThumbnail(messageId: baseMessage.id)
  244. }
  245. }
  246. caption = nil
  247. statusType = "text"
  248. let webVideo = WebVideo.init(videoMessage)
  249. video = webVideo.objectDict()
  250. }
  251. private func addAudioMessage(_ message: BaseMessage) {
  252. let audioMessage = message as! AudioMessage
  253. type = "audio"
  254. body = nil
  255. thumbnail = nil
  256. caption = nil
  257. statusType = "text"
  258. let webAudio = WebAudio.init(audioMessage)
  259. audio = webAudio.objectDict()
  260. }
  261. private func addLocationMessage(_ message: BaseMessage) {
  262. let locationMessage = message as! LocationMessage
  263. type = "location"
  264. body = nil
  265. thumbnail = nil
  266. caption = nil
  267. statusType = "text"
  268. let webLocation = WebLocation.init(locationMessage)
  269. location = webLocation.objectDict()
  270. }
  271. private func addFileMessage(_ message: BaseMessage, forConversationsRequest: Bool, session: WCSession) {
  272. let fileMessage = message as! FileMessage
  273. body = nil
  274. thumbnail = nil
  275. if let fileThumbnail = fileMessage.thumbnail, fileThumbnail.data != nil {
  276. if fileMessage.blobThumbnailId != nil {
  277. if !session.requestedThumbnails(contains: fileMessage.blobThumbnailId) {
  278. let webThumbnail = WebThumbnail.init(fileMessage, onlyThumbnail: true)
  279. thumbnail = webThumbnail.objectDict()
  280. if !forConversationsRequest {
  281. session.addRequestedThumbnail(messageId: fileMessage.blobThumbnailId)
  282. }
  283. }
  284. } else {
  285. let webThumbnail = WebThumbnail.init(fileMessage, onlyThumbnail: true)
  286. thumbnail = webThumbnail.objectDict()
  287. }
  288. }
  289. if let fileCaption = fileMessage.getCaption() {
  290. caption = fileCaption
  291. }
  292. statusType = "text"
  293. if fileMessage.renderFileImageMessage() {
  294. type = "image"
  295. }
  296. else if fileMessage.renderFileVideoMessage() {
  297. type = "video"
  298. let webVideo = WebVideo.init(fileMessage)
  299. video = webVideo.objectDict()
  300. }
  301. else {
  302. type = "file"
  303. let webFile = WebFile.init(fileMessage)
  304. file = webFile.objectDict()
  305. }
  306. }
  307. private func addSystemMessage(_ message: BaseMessage) {
  308. let systemMessage = message as! SystemMessage
  309. if systemMessage.isCallType() {
  310. // voip
  311. type = "voipStatus"
  312. body = nil
  313. thumbnail = nil
  314. caption = nil
  315. state = nil
  316. statusType = "text"
  317. if systemMessage.arg != nil {
  318. do {
  319. let argDict = try JSONSerialization.jsonObject(with: systemMessage.arg, options: .allowFragments) as! [AnyHashable: Any]
  320. isOutbox = argDict["CallInitiator"] as! Bool
  321. }
  322. catch {
  323. isOutbox = false
  324. }
  325. } else {
  326. isOutbox = true
  327. }
  328. let webVoip = WebVoip.init(systemMessage)
  329. voip = webVoip.objectDict()
  330. } else {
  331. type = "text"
  332. body = systemMessage.format()
  333. thumbnail = nil
  334. isStatus = true
  335. caption = nil
  336. statusType = "text"
  337. }
  338. }
  339. private func addBallotMessage(_ message: BaseMessage) {
  340. type = "ballot"
  341. isStatus = false
  342. statusType = "text"
  343. }
  344. }
  345. struct MessageEvents {
  346. var events = [[String: Any]]()
  347. init(baseMessage: BaseMessage) {
  348. if baseMessage.isOwn.boolValue == true {
  349. if baseMessage.remoteSentDate != nil {
  350. var event = [String: Any]()
  351. event.updateValue("sent", forKey: "type")
  352. event.updateValue(Int((baseMessage.remoteSentDate.timeIntervalSince1970)), forKey: "date")
  353. events.append(event)
  354. }
  355. if baseMessage.deliveryDate != nil {
  356. var event = [String: Any]()
  357. event.updateValue("delivered", forKey: "type")
  358. event.updateValue(Int((baseMessage.deliveryDate.timeIntervalSince1970)), forKey: "date")
  359. events.append(event)
  360. }
  361. if baseMessage.readDate != nil {
  362. var event = [String: Any]()
  363. event.updateValue("read", forKey: "type")
  364. event.updateValue(Int((baseMessage.readDate.timeIntervalSince1970)), forKey: "date")
  365. events.append(event)
  366. }
  367. } else {
  368. if baseMessage.date != nil {
  369. var event = [String: Any]()
  370. event.updateValue("sent", forKey: "type")
  371. event.updateValue(Int((baseMessage.remoteSentDate.timeIntervalSince1970)), forKey: "date")
  372. events.append(event)
  373. }
  374. if baseMessage.deliveryDate != nil {
  375. var event = [String: Any]()
  376. event.updateValue("delivered", forKey: "type")
  377. event.updateValue(Int((baseMessage.deliveryDate.timeIntervalSince1970)), forKey: "date")
  378. events.append(event)
  379. }
  380. if baseMessage.readDate != nil {
  381. var event = [String: Any]()
  382. event.updateValue("read", forKey: "type")
  383. event.updateValue(Int((baseMessage.readDate.timeIntervalSince1970)), forKey: "date")
  384. events.append(event)
  385. }
  386. if baseMessage.userackDate != nil {
  387. var event = [String: Any]()
  388. event.updateValue("acked", forKey: "type")
  389. event.updateValue(Int((baseMessage.userackDate.timeIntervalSince1970)), forKey: "date")
  390. events.append(event)
  391. }
  392. }
  393. }
  394. }
  395. struct WebBlob {
  396. var blob: Data?
  397. var type: String
  398. var name: String
  399. init(imageMessage: ImageMessage) {
  400. if imageMessage.image.data != nil {
  401. blob = imageMessage.image.data
  402. }
  403. name = imageMessage.blobGetWebFilename()
  404. type = "image/\(MEDIA_EXTENSION_IMAGE)"
  405. }
  406. init(videoMessage: VideoMessage) {
  407. if videoMessage.video.data != nil {
  408. blob = videoMessage.video.data
  409. }
  410. name = videoMessage.blobGetWebFilename()
  411. type = "video/\(MEDIA_EXTENSION_VIDEO)"
  412. }
  413. init(audioMessage: AudioMessage) {
  414. if audioMessage.audio.data != nil {
  415. blob = audioMessage.audio.data
  416. }
  417. name = audioMessage.blobGetWebFilename()
  418. type = "audio/\(MEDIA_EXTENSION_VIDEO)"
  419. }
  420. init(fileMessage: FileMessage) {
  421. if fileMessage.data.data != nil {
  422. blob = fileMessage.data.data
  423. }
  424. name = fileMessage.blobGetWebFilename()
  425. type = fileMessage.mimeType
  426. }
  427. func objectDict() -> [String: Any] {
  428. var objectDict:[String: Any] = ["type": type, "name": name]
  429. if blob != nil {
  430. objectDict.updateValue(blob!, forKey: "blob")
  431. }
  432. return objectDict
  433. }
  434. }
  435. struct WebThumbnail {
  436. var height: Int
  437. var width: Int
  438. var preview: Data
  439. var image: Data?
  440. init(imageMessage: ImageMessage, onlyThumbnail: Bool) {
  441. var size: CGSize
  442. var useThumbnail: Bool = true
  443. if !onlyThumbnail && imageMessage.image != nil {
  444. if imageMessage.image.data != nil {
  445. useThumbnail = false
  446. }
  447. } else {
  448. if imageMessage.thumbnail == nil {
  449. useThumbnail = false
  450. }
  451. if imageMessage.thumbnail != nil {
  452. if imageMessage.thumbnail.data == nil {
  453. useThumbnail = false
  454. }
  455. }
  456. }
  457. if useThumbnail == true {
  458. size = MediaConverter.getWebThumbnailSize(forImageData: imageMessage.thumbnail.data)
  459. preview = MediaConverter.getWebPreviewData(imageMessage.thumbnail.data)
  460. } else {
  461. size = MediaConverter.getWebThumbnailSize(forImageData: imageMessage.image.data)
  462. preview = MediaConverter.getWebPreviewData(imageMessage.image.data)
  463. }
  464. height = Int(size.height)
  465. width = Int(size.width)
  466. if !onlyThumbnail {
  467. if useThumbnail == true {
  468. image = MediaConverter.getWebThumbnailData(imageMessage.thumbnail.data)
  469. } else {
  470. image = MediaConverter.getWebThumbnailData(imageMessage.image.data)
  471. }
  472. }
  473. }
  474. init(_ videoMessage: VideoMessage, onlyThumbnail: Bool) {
  475. let size = MediaConverter.getWebThumbnailSize(forImageData: videoMessage.thumbnail.data)
  476. height = Int(size.height)
  477. width = Int(size.width)
  478. if let tmpPreview = MediaConverter.getWebPreviewData(videoMessage.thumbnail.data) {
  479. preview = tmpPreview
  480. } else {
  481. height = Int(44)
  482. width = Int(44)
  483. preview = UIImage.init(named: "Thumbnail")!.pngData()!
  484. }
  485. if !onlyThumbnail {
  486. image = MediaConverter.getWebThumbnailData(videoMessage.thumbnail.data)
  487. }
  488. }
  489. init(_ fileMessage: FileMessage, onlyThumbnail: Bool) {
  490. let size = MediaConverter.getWebThumbnailSize(forImageData: fileMessage.thumbnail.data)
  491. height = Int(size.height)
  492. width = Int(size.width)
  493. if let tmpPreview = MediaConverter.getWebPreviewData(fileMessage.thumbnail.data) {
  494. preview = tmpPreview
  495. } else {
  496. height = Int(44)
  497. width = Int(44)
  498. preview = UIImage.init(named: "Thumbnail")!.pngData()!
  499. }
  500. if !onlyThumbnail {
  501. image = MediaConverter.getWebThumbnailData(fileMessage.thumbnail.data)
  502. }
  503. }
  504. func objectDict() -> [String: Any] {
  505. return ["height": height, "width": width, "preview": preview]
  506. }
  507. }
  508. struct WebVideo {
  509. var duration: Int
  510. var size: Int
  511. init(_ videoMessage: VideoMessage) {
  512. duration = videoMessage.duration.intValue
  513. size = videoMessage.videoSize.intValue
  514. }
  515. init (_ fileMessage: FileMessage) {
  516. if let videoDuration = fileMessage.duration {
  517. duration = videoDuration.intValue
  518. } else {
  519. duration = 0
  520. }
  521. if let videoSize = fileMessage.fileSize {
  522. size = videoSize.intValue
  523. } else {
  524. size = 0
  525. }
  526. }
  527. func objectDict() -> [String: Any] {
  528. return ["duration": duration, "size": size]
  529. }
  530. }
  531. struct WebAudio {
  532. var duration: Int
  533. init(_ audioMessage: AudioMessage) {
  534. duration = audioMessage.duration.intValue
  535. }
  536. func objectDict() -> [String: Any] {
  537. return ["duration": duration]
  538. }
  539. }
  540. struct WebLocation {
  541. var lat: Float
  542. var lon: Float
  543. var accuracy: Float
  544. var address: String?
  545. var description: String?
  546. init(_ locationMessage: LocationMessage) {
  547. lat = locationMessage.latitude.floatValue
  548. lon = locationMessage.longitude.floatValue
  549. accuracy = locationMessage.accuracy.floatValue
  550. address = nil
  551. description = locationMessage.poiName
  552. }
  553. func objectDict() -> [String: Any] {
  554. var objectDict:[String: Any] = ["lat": lat, "lon": lon, "accuracy": accuracy]
  555. if address != nil {
  556. objectDict.updateValue(address!, forKey: "address")
  557. }
  558. if description != nil {
  559. objectDict.updateValue(description!, forKey: "description")
  560. }
  561. return objectDict
  562. }
  563. }
  564. struct WebFile {
  565. var name: String
  566. var size: Int
  567. var type: String
  568. var inApp: Bool
  569. init(_ fileMessage: FileMessage) {
  570. name = fileMessage.fileName
  571. size = fileMessage.fileSize.intValue
  572. type = fileMessage.mimeType
  573. inApp = false
  574. }
  575. func objectDict() -> [String: Any] {
  576. return ["name": name, "size": size, "type": type, "inApp": inApp]
  577. }
  578. }
  579. struct WebVoip {
  580. var status: Int
  581. var duration: Int?
  582. var reason: Int?
  583. init(_ systemMessage: SystemMessage) {
  584. switch systemMessage.type.intValue {
  585. case kSystemMessageCallMissed:
  586. status = 1
  587. break
  588. case kSystemMessageCallRejected:
  589. status = 3
  590. break
  591. case kSystemMessageCallRejectedBusy:
  592. status = 3
  593. break
  594. case kSystemMessageCallRejectedTimeout:
  595. status = 3
  596. break
  597. case kSystemMessageCallEnded:
  598. if systemMessage.haveCallTime() {
  599. status = 2
  600. } else {
  601. status = 4
  602. }
  603. break
  604. case kSystemMessageCallRejectedDisabled:
  605. status = 3
  606. break
  607. default:
  608. status = 2
  609. }
  610. if let callTime = systemMessage.callTime() {
  611. duration = Int(DateFormatter.totalSeconds(callTime))
  612. }
  613. switch systemMessage.type.intValue {
  614. case kSystemMessageCallRejected:
  615. reason = 3
  616. break
  617. case kSystemMessageCallRejectedBusy:
  618. reason = 1
  619. break
  620. case kSystemMessageCallRejectedTimeout:
  621. reason = 2
  622. break
  623. case kSystemMessageCallRejectedDisabled:
  624. reason = 4
  625. break
  626. default:
  627. break
  628. }
  629. }
  630. func objectDict() -> [String: Any] {
  631. var objectDict:[String: Any] = ["status": status]
  632. if duration != nil {
  633. objectDict.updateValue(duration!, forKey: "duration")
  634. }
  635. if reason != nil {
  636. objectDict.updateValue(reason!, forKey: "reason")
  637. }
  638. return objectDict
  639. }
  640. }
  641. extension Data {
  642. var integer: UInt64 {
  643. return withUnsafeBytes { $0.pointee }
  644. }
  645. }
  646. extension Numeric {
  647. var makeData: Data {
  648. var source = self
  649. // This will return 1 byte for 8-bit, 2 bytes for 16-bit, 4 bytes for 32-bit and 8 bytes for 64-bit binary integers. For floating point types it will return 4 bytes for single-precision, 8 bytes for double-precision and 16 bytes for extended precision.
  650. return Data(bytes: &source, count: MemoryLayout<Self>.size)
  651. }
  652. }