Wrapper.swift 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394
  1. import Foundation
  2. import UIKit
  3. import AVFoundation
  4. public class DcAccounts {
  5. /// The application group identifier defines a group of apps or extensions that have access to a shared container.
  6. /// The ID is created in the apple developer portal and can be changed there.
  7. let applicationGroupIdentifier = "group.chat.delta.ios"
  8. var accountsPointer: OpaquePointer?
  9. public init() {
  10. }
  11. deinit {
  12. if accountsPointer == nil { return }
  13. dc_accounts_unref(accountsPointer)
  14. accountsPointer = nil
  15. }
  16. public func migrateAccount(dbLocation: String) -> Int {
  17. return Int(dc_accounts_migrate_account(accountsPointer, dbLocation))
  18. }
  19. public func addAccount() -> Int {
  20. return Int(dc_accounts_add_account(accountsPointer))
  21. }
  22. public func getAccount(id: Int) -> DcContext {
  23. let contextPointer = dc_accounts_get_account(accountsPointer, UInt32(id))
  24. return DcContext(contextPointer: contextPointer)
  25. }
  26. public func getAll() -> [Int] {
  27. let cAccounts = dc_accounts_get_all(accountsPointer)
  28. return DcUtils.copyAndFreeArray(inputArray: cAccounts)
  29. }
  30. public func get() -> DcContext {
  31. let cPtr = dc_accounts_get_selected_account(accountsPointer)
  32. return DcContext(contextPointer: cPtr)
  33. }
  34. public func maybeNetwork() {
  35. dc_accounts_maybe_network(accountsPointer)
  36. }
  37. public func maybeStartIo() {
  38. if get().isConfigured() {
  39. dc_accounts_start_io(accountsPointer)
  40. }
  41. }
  42. public func stopIo() {
  43. dc_accounts_stop_io(accountsPointer)
  44. }
  45. public func selectAccount(id: Int) -> Bool {
  46. return dc_accounts_select_account(accountsPointer, UInt32(id)) == 1
  47. }
  48. public func removeAccount(id: Int) -> Bool {
  49. return dc_accounts_remove_account(accountsPointer, UInt32(id)) == 1
  50. }
  51. public func importAccount(filePath: String) -> Int {
  52. return Int(dc_accounts_import_account(accountsPointer, filePath))
  53. }
  54. public func getEventEmitter() -> DcAccountsEventEmitter {
  55. let eventEmitterPointer = dc_accounts_get_event_emitter(accountsPointer)
  56. return DcAccountsEventEmitter(eventEmitterPointer: eventEmitterPointer)
  57. }
  58. public func openDatabase() {
  59. var version = ""
  60. if let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
  61. version += " " + appVersion
  62. }
  63. if let sharedDbLocation = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: applicationGroupIdentifier) {
  64. accountsPointer = dc_accounts_new("iOS\(version)", sharedDbLocation.path)
  65. }
  66. }
  67. public func closeDatabase() {
  68. dc_accounts_unref(accountsPointer)
  69. accountsPointer = nil
  70. }
  71. }
  72. public class DcContext {
  73. public var logger: Logger?
  74. var contextPointer: OpaquePointer?
  75. public var lastErrorString: String?
  76. public var lastWarningString: String = "" // temporary thing to get a grip on some weird errors
  77. public var maxConfigureProgress: Int = 0 // temporary thing to get a grip on some weird errors
  78. public init() {
  79. }
  80. public init(contextPointer: OpaquePointer?) {
  81. self.contextPointer = contextPointer
  82. }
  83. deinit {
  84. if contextPointer == nil { return } // avoid a warning about a "careless call"
  85. dc_context_unref(contextPointer)
  86. contextPointer = nil
  87. }
  88. // viewType: one of DC_MSG_*
  89. public func newMessage(viewType: Int32) -> DcMsg {
  90. let messagePointer = dc_msg_new(contextPointer, viewType)
  91. return DcMsg(pointer: messagePointer)
  92. }
  93. public func getMessage(id: Int) -> DcMsg {
  94. let messagePointer = dc_get_msg(contextPointer, UInt32(id))
  95. return DcMsg(pointer: messagePointer)
  96. }
  97. public func sendMessage(chatId: Int, message: DcMsg) {
  98. dc_send_msg(contextPointer, UInt32(chatId), message.messagePointer)
  99. }
  100. // TODO: remove count and from parameters if we don't use it
  101. public func getMessageIds(chatId: Int, count: Int? = nil, from: Int? = nil) -> [Int] {
  102. let start = CFAbsoluteTimeGetCurrent()
  103. let cMessageIds = getChatMessages(chatId: chatId)
  104. let diff = CFAbsoluteTimeGetCurrent() - start
  105. logger?.info("⏰ getMessageIds: \(diff) s")
  106. let ids: [Int]
  107. if let from = from {
  108. // skip last part
  109. ids = DcUtils.copyAndFreeArrayWithOffset(inputArray: cMessageIds, len: count, skipEnd: from)
  110. } else if let count = count {
  111. // skip first part
  112. ids = DcUtils.copyAndFreeArrayWithLen(inputArray: cMessageIds, len: count)
  113. } else {
  114. ids = DcUtils.copyAndFreeArray(inputArray: cMessageIds)
  115. }
  116. return ids
  117. }
  118. public func createContact(name: String, email: String) -> Int {
  119. return Int(dc_create_contact(contextPointer, name, email))
  120. }
  121. public func deleteContact(contactId: Int) -> Bool {
  122. return dc_delete_contact(self.contextPointer, UInt32(contactId)) == 1
  123. }
  124. public func getContacts(flags: Int32, queryString: String? = nil) -> [Int] {
  125. let start = CFAbsoluteTimeGetCurrent()
  126. let cContacts = dc_get_contacts(contextPointer, UInt32(flags), queryString)
  127. let diff = CFAbsoluteTimeGetCurrent() - start
  128. logger?.info("⏰ getContacts: \(diff) s")
  129. return DcUtils.copyAndFreeArray(inputArray: cContacts)
  130. }
  131. public func getContact(id: Int) -> DcContact {
  132. let contactPointer = dc_get_contact(contextPointer, UInt32(id))
  133. return DcContact(contactPointer: contactPointer)
  134. }
  135. public func blockContact(id: Int) {
  136. dc_block_contact(contextPointer, UInt32(id), 1)
  137. }
  138. public func unblockContact(id: Int) {
  139. dc_block_contact(contextPointer, UInt32(id), 0)
  140. }
  141. public func getBlockedContacts() -> [Int] {
  142. let cBlockedContacts = dc_get_blocked_contacts(contextPointer)
  143. return DcUtils.copyAndFreeArray(inputArray: cBlockedContacts)
  144. }
  145. public func addContacts(contactString: String) {
  146. dc_add_address_book(contextPointer, contactString)
  147. }
  148. public func getChat(chatId: Int) -> DcChat {
  149. let chatPointer = dc_get_chat(contextPointer, UInt32(chatId))
  150. return DcChat(chatPointer: chatPointer)
  151. }
  152. public func getChatIdByContactId(contactId: Int) -> Int {
  153. return Int(dc_get_chat_id_by_contact_id(contextPointer, UInt32(contactId)))
  154. }
  155. public func getChatIdByContactIdOld(_ contactId: Int) -> Int? {
  156. // deprecated function, use getChatIdByContactId() and check for != 0 as for all other places IDs are used
  157. let chatId = dc_get_chat_id_by_contact_id(contextPointer, UInt32(contactId))
  158. if chatId == 0 {
  159. return nil
  160. } else {
  161. return Int(chatId)
  162. }
  163. }
  164. @discardableResult
  165. public func decideOnContactRequest(_ messageId: Int, _ decision: Int32) -> DcChat {
  166. let chatId = dc_decide_on_contact_request(contextPointer, UInt32(messageId), decision)
  167. return getChat(chatId: Int(chatId))
  168. }
  169. public func getChatlist(flags: Int32, queryString: String?, queryId: Int) -> DcChatlist {
  170. let start = CFAbsoluteTimeGetCurrent()
  171. let chatlistPointer = dc_get_chatlist(contextPointer, flags, queryString, UInt32(queryId))
  172. let chatlist = DcChatlist(chatListPointer: chatlistPointer)
  173. let diff = CFAbsoluteTimeGetCurrent() - start
  174. logger?.info("⏰ getChatlist: \(diff) s")
  175. return chatlist
  176. }
  177. public func sendMsgSync(chatId: Int, msg: DcMsg) {
  178. dc_send_msg_sync(contextPointer, UInt32(chatId), msg.messagePointer)
  179. }
  180. public func getChatMedia(chatId: Int, messageType: Int32, messageType2: Int32, messageType3: Int32) -> [Int] {
  181. guard let messagesPointer = dc_get_chat_media(contextPointer, UInt32(chatId), messageType, messageType2, messageType3) else {
  182. return []
  183. }
  184. let messageIds: [Int] = DcUtils.copyAndFreeArray(inputArray: messagesPointer)
  185. return messageIds
  186. }
  187. @discardableResult
  188. public func createChatByContactId(contactId: Int) -> Int {
  189. return Int(dc_create_chat_by_contact_id(contextPointer, UInt32(contactId)))
  190. }
  191. public func createGroupChat(verified: Bool, name: String) -> Int {
  192. return Int(dc_create_group_chat(contextPointer, verified ? 1 : 0, name))
  193. }
  194. public func addContactToChat(chatId: Int, contactId: Int) -> Bool {
  195. return dc_add_contact_to_chat(contextPointer, UInt32(chatId), UInt32(contactId)) == 1
  196. }
  197. public func removeContactFromChat(chatId: Int, contactId: Int) -> Bool {
  198. return dc_remove_contact_from_chat(contextPointer, UInt32(chatId), UInt32(contactId)) == 1
  199. }
  200. public func setChatName(chatId: Int, name: String) -> Bool {
  201. return dc_set_chat_name(contextPointer, UInt32(chatId), name) == 1
  202. }
  203. public func deleteChat(chatId: Int) {
  204. dc_delete_chat(contextPointer, UInt32(chatId))
  205. }
  206. public func archiveChat(chatId: Int, archive: Bool) {
  207. dc_set_chat_visibility(contextPointer, UInt32(chatId), Int32(archive ? DC_CHAT_VISIBILITY_ARCHIVED : DC_CHAT_VISIBILITY_NORMAL))
  208. }
  209. public func setChatVisibility(chatId: Int, visibility: Int32) {
  210. dc_set_chat_visibility(contextPointer, UInt32(chatId), visibility)
  211. }
  212. public func marknoticedChat(chatId: Int) {
  213. dc_marknoticed_chat(self.contextPointer, UInt32(chatId))
  214. }
  215. public func getSecurejoinQr (chatId: Int) -> String? {
  216. if let cString = dc_get_securejoin_qr(self.contextPointer, UInt32(chatId)) {
  217. let swiftString = String(cString: cString)
  218. dc_str_unref(cString)
  219. return swiftString
  220. }
  221. return nil
  222. }
  223. public func joinSecurejoin (qrCode: String) -> Int {
  224. return Int(dc_join_securejoin(contextPointer, qrCode))
  225. }
  226. public func checkQR(qrCode: String) -> DcLot {
  227. return DcLot(dc_check_qr(contextPointer, qrCode))
  228. }
  229. public func setConfigFromQR(qrCode: String) -> Bool {
  230. return dc_set_config_from_qr(contextPointer, qrCode) != 0
  231. }
  232. public func stopOngoingProcess() {
  233. dc_stop_ongoing_process(contextPointer)
  234. }
  235. public func getInfo() -> String {
  236. if let cString = dc_get_info(contextPointer) {
  237. let info = String(cString: cString)
  238. dc_str_unref(cString)
  239. return info
  240. }
  241. return "ErrGetInfo"
  242. }
  243. public func getContactEncrInfo(contactId: Int) -> String {
  244. if let cString = dc_get_contact_encrinfo(contextPointer, UInt32(contactId)) {
  245. let switftString = String(cString: cString)
  246. dc_str_unref(cString)
  247. return switftString
  248. }
  249. return "ErrGetContactEncrInfo"
  250. }
  251. public func interruptIdle() {
  252. }
  253. public func getEventEmitter() -> DcEventEmitter {
  254. let eventEmitterPointer = dc_get_event_emitter(contextPointer)
  255. return DcEventEmitter(eventEmitterPointer: eventEmitterPointer)
  256. }
  257. public func openDatabase(dbFile: String) {
  258. var version = ""
  259. if let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
  260. version += " " + appVersion
  261. }
  262. contextPointer = dc_context_new("iOS" + version, dbFile, nil)
  263. }
  264. public func closeDatabase() {
  265. dc_context_unref(contextPointer)
  266. contextPointer = nil
  267. }
  268. public func maybeStartIo() {
  269. if isConfigured() {
  270. dc_start_io(contextPointer)
  271. }
  272. }
  273. public func stopIo() {
  274. dc_stop_io(contextPointer)
  275. }
  276. public func setStockTranslation(id: Int32, localizationKey: String) {
  277. dc_set_stock_translation(contextPointer, UInt32(id), String.localized(localizationKey))
  278. }
  279. public func getDraft(chatId: Int) -> DcMsg? {
  280. if let draft = dc_get_draft(contextPointer, UInt32(chatId)) {
  281. return DcMsg(pointer: draft)
  282. }
  283. return nil
  284. }
  285. public func setDraft(chatId: Int, message: DcMsg?) {
  286. dc_set_draft(contextPointer, UInt32(chatId), message?.messagePointer)
  287. }
  288. public func getFreshMessages() -> DcArray {
  289. return DcArray(arrayPointer: dc_get_fresh_msgs(contextPointer))
  290. }
  291. public func markSeenMessages(messageIds: [UInt32]) {
  292. messageIds.withUnsafeBufferPointer { ptr in
  293. dc_markseen_msgs(contextPointer, ptr.baseAddress, Int32(ptr.count))
  294. }
  295. }
  296. private func getChatMessages(chatId: Int) -> OpaquePointer {
  297. return dc_get_chat_msgs(contextPointer, UInt32(chatId), UInt32(DC_GCM_ADDDAYMARKER), 0)
  298. }
  299. public func getMsgInfo(msgId: Int) -> String {
  300. if let cString = dc_get_msg_info(self.contextPointer, UInt32(msgId)) {
  301. let swiftString = String(cString: cString)
  302. dc_str_unref(cString)
  303. return swiftString
  304. }
  305. return "ErrGetMsgInfo"
  306. }
  307. public func getMsgHtml(msgId: Int) -> String {
  308. guard let cString = dc_get_msg_html(self.contextPointer, UInt32(msgId)) else { return "" }
  309. let swiftString = String(cString: cString)
  310. dc_str_unref(cString)
  311. return swiftString
  312. }
  313. public func deleteMessage(msgId: Int) {
  314. dc_delete_msgs(contextPointer, [UInt32(msgId)], 1)
  315. }
  316. public func deleteMessages(msgIds: [Int]) {
  317. dc_delete_msgs(contextPointer, msgIds.compactMap { UInt32($0) }, Int32(msgIds.count))
  318. }
  319. public func forwardMessage(with msgId: Int, to chat: Int) {
  320. dc_forward_msgs(contextPointer, [UInt32(msgId)], 1, UInt32(chat))
  321. }
  322. public func forwardMessages(with msgIds: [Int], to chat: Int) {
  323. dc_forward_msgs(contextPointer, msgIds.compactMap { UInt32($0) }, Int32(msgIds.count), UInt32(chat))
  324. }
  325. public func sendTextInChat(id: Int, message: String) {
  326. dc_send_text_msg(contextPointer, UInt32(id), message)
  327. }
  328. public func initiateKeyTransfer() -> String? {
  329. if let cString = dc_initiate_key_transfer(self.contextPointer) {
  330. let swiftString = String(cString: cString)
  331. dc_str_unref(cString)
  332. return swiftString
  333. }
  334. return nil
  335. }
  336. public func continueKeyTransfer(msgId: Int, setupCode: String) -> Bool {
  337. return dc_continue_key_transfer(self.contextPointer, UInt32(msgId), setupCode) != 0
  338. }
  339. public func configure() {
  340. maxConfigureProgress = 0
  341. lastWarningString = ""
  342. dc_configure(contextPointer)
  343. }
  344. public func setChatMuteDuration(chatId: Int, duration: Int) {
  345. dc_set_chat_mute_duration(self.contextPointer, UInt32(chatId), Int64(duration))
  346. }
  347. public func setChatEphemeralTimer(chatId: Int, duration: Int) {
  348. dc_set_chat_ephemeral_timer(self.contextPointer, UInt32(chatId), UInt32(duration))
  349. }
  350. public func getChatEphemeralTimer(chatId: Int) -> Int {
  351. return Int(dc_get_chat_ephemeral_timer(self.contextPointer, UInt32(chatId)))
  352. }
  353. public func getConfig(_ key: String) -> String? {
  354. guard let cString = dc_get_config(self.contextPointer, key) else { return nil }
  355. let value = String(cString: cString)
  356. dc_str_unref(cString)
  357. if value.isEmpty {
  358. return nil
  359. }
  360. return value
  361. }
  362. public func setConfig(_ key: String, _ value: String?) {
  363. if let v = value {
  364. dc_set_config(self.contextPointer, key, v)
  365. } else {
  366. dc_set_config(self.contextPointer, key, nil)
  367. }
  368. }
  369. public func getConfigBool(_ key: String) -> Bool {
  370. return strToBool(getConfig(key))
  371. }
  372. public func setConfigBool(_ key: String, _ value: Bool) {
  373. let vStr = value ? "1" : "0"
  374. setConfig(key, vStr)
  375. }
  376. public func getConfigInt(_ key: String) -> Int {
  377. if let str = getConfig(key) {
  378. return Int(str) ?? 0
  379. }
  380. return 0
  381. }
  382. public func setConfigInt(_ key: String, _ value: Int) {
  383. setConfig(key, String(value))
  384. }
  385. public func getUnreadMessages(chatId: Int) -> Int {
  386. return Int(dc_get_fresh_msg_cnt(contextPointer, UInt32(chatId)))
  387. }
  388. public func estimateDeletionCnt(fromServer: Bool, timeout: Int) -> Int {
  389. return Int(dc_estimate_deletion_cnt(contextPointer, fromServer ? 1 : 0, Int64(timeout)))
  390. }
  391. public func isConfigured() -> Bool {
  392. return dc_is_configured(contextPointer) != 0
  393. }
  394. public func getSelfAvatarImage() -> UIImage? {
  395. guard let fileName = selfavatar else { return nil }
  396. let path: URL = URL(fileURLWithPath: fileName, isDirectory: false)
  397. if path.isFileURL {
  398. do {
  399. let data = try Data(contentsOf: path)
  400. return UIImage(data: data)
  401. } catch {
  402. logger?.warning("failed to load image: \(fileName), \(error)")
  403. return nil
  404. }
  405. }
  406. return nil
  407. }
  408. public func setChatProfileImage(chatId: Int, path: String?) {
  409. dc_set_chat_profile_image(contextPointer, UInt32(chatId), path)
  410. }
  411. @discardableResult
  412. public func addDeviceMessage(label: String?, msg: DcMsg) -> Int {
  413. return Int(dc_add_device_msg(contextPointer, label, msg.cptr))
  414. }
  415. public func getProviderFromEmail(addr: String) -> DcProvider? {
  416. guard let dcProviderPointer = dc_provider_new_from_email(contextPointer, addr) else { return nil }
  417. return DcProvider(dcProviderPointer)
  418. }
  419. public func imex(what: Int32, directory: String) {
  420. dc_imex(contextPointer, what, directory, nil)
  421. }
  422. public func imexHasBackup(filePath: String) -> String? {
  423. var file: String?
  424. if let cString = dc_imex_has_backup(contextPointer, filePath) {
  425. file = String(cString: cString)
  426. dc_str_unref(cString)
  427. }
  428. return file
  429. }
  430. public func isSendingLocationsToChat(chatId: Int) -> Bool {
  431. return dc_is_sending_locations_to_chat(contextPointer, UInt32(chatId)) == 1
  432. }
  433. public func sendLocationsToChat(chatId: Int, seconds: Int) {
  434. dc_send_locations_to_chat(contextPointer, UInt32(chatId), Int32(seconds))
  435. }
  436. public func setLocation(latitude: Double, longitude: Double, accuracy: Double) {
  437. dc_set_location(contextPointer, latitude, longitude, accuracy)
  438. }
  439. public func searchMessages(chatId: Int = 0, searchText: String) -> [Int] {
  440. let start = CFAbsoluteTimeGetCurrent()
  441. guard let arrayPointer = dc_search_msgs(contextPointer, UInt32(chatId), searchText) else {
  442. return []
  443. }
  444. let messageIds = DcUtils.copyAndFreeArray(inputArray: arrayPointer)
  445. let diff = CFAbsoluteTimeGetCurrent() - start
  446. logger?.info("⏰ searchMessages: \(diff) s")
  447. return messageIds
  448. }
  449. // call dc_maybe_network() from a worker thread.
  450. public func maybeNetwork() {
  451. dc_maybe_network(contextPointer)
  452. }
  453. // also, there is no much worth in adding a separate function or so
  454. // for each config option - esp. if they are just forwarded to the core
  455. // and set/get only at one line of code each.
  456. // this adds a complexity that can be avoided -
  457. // and makes grep harder as these names are typically named following different guidelines.
  458. public var displayname: String? {
  459. get { return getConfig("displayname") }
  460. set { setConfig("displayname", newValue) }
  461. }
  462. public var selfstatus: String? {
  463. get { return getConfig("selfstatus") }
  464. set { setConfig("selfstatus", newValue) }
  465. }
  466. public var selfavatar: String? {
  467. get { return getConfig("selfavatar") }
  468. set { setConfig("selfavatar", newValue) }
  469. }
  470. public var addr: String? {
  471. get { return getConfig("addr") }
  472. set { setConfig("addr", newValue) }
  473. }
  474. public var mailServer: String? {
  475. get { return getConfig("mail_server") }
  476. set { setConfig("mail_server", newValue) }
  477. }
  478. public var mailUser: String? {
  479. get { return getConfig("mail_user") }
  480. set { setConfig("mail_user", newValue) }
  481. }
  482. public var mailPw: String? {
  483. get { return getConfig("mail_pw") }
  484. set { setConfig("mail_pw", newValue) }
  485. }
  486. public var mailPort: String? {
  487. get { return getConfig("mail_port") }
  488. set { setConfig("mail_port", newValue) }
  489. }
  490. public var sendServer: String? {
  491. get { return getConfig("send_server") }
  492. set { setConfig("send_server", newValue) }
  493. }
  494. public var sendUser: String? {
  495. get { return getConfig("send_user") }
  496. set { setConfig("send_user", newValue) }
  497. }
  498. public var sendPw: String? {
  499. get { return getConfig("send_pw") }
  500. set { setConfig("send_pw", newValue) }
  501. }
  502. public var sendPort: String? {
  503. get { return getConfig("send_port") }
  504. set { setConfig("send_port", newValue) }
  505. }
  506. public var certificateChecks: Int {
  507. get {
  508. if let str = getConfig("imap_certificate_checks") {
  509. return Int(str) ?? 0
  510. } else {
  511. return 0
  512. }
  513. }
  514. set {
  515. setConfig("smtp_certificate_checks", "\(newValue)")
  516. setConfig("imap_certificate_checks", "\(newValue)")
  517. }
  518. }
  519. private var serverFlags: Int {
  520. // IMAP-/SMTP-flags as a combination of DC_LP flags
  521. get {
  522. if let str = getConfig("server_flags") {
  523. return Int(str) ?? 0
  524. } else {
  525. return 0
  526. }
  527. }
  528. set {
  529. setConfig("server_flags", "\(newValue)")
  530. }
  531. }
  532. public func setAuthFlags(flags: Int) {
  533. var sf = serverFlags
  534. sf = sf & ~0x6 // DC_LP_AUTH_FLAGS
  535. sf = sf | flags
  536. serverFlags = sf
  537. }
  538. public func getAuthFlags() -> Int {
  539. var sf = serverFlags
  540. sf = sf & 0x6 // DC_LP_AUTH_FLAGS
  541. return sf
  542. }
  543. public var e2eeEnabled: Bool {
  544. get { return getConfigBool("e2ee_enabled") }
  545. set { setConfigBool("e2ee_enabled", newValue) }
  546. }
  547. public var mdnsEnabled: Bool {
  548. get { return getConfigBool("mdns_enabled") }
  549. set { setConfigBool("mdns_enabled", newValue) }
  550. }
  551. public var showEmails: Int {
  552. // one of DC_SHOW_EMAILS_*
  553. get { return getConfigInt("show_emails") }
  554. set { setConfigInt("show_emails", newValue) }
  555. }
  556. // do not use. use DcContext::isConfigured() instead
  557. public var configured: Bool {
  558. return getConfigBool("configured")
  559. }
  560. }
  561. public class DcAccountsEventEmitter {
  562. private var eventEmitterPointer: OpaquePointer?
  563. // takes ownership of specified pointer
  564. public init(eventEmitterPointer: OpaquePointer?) {
  565. self.eventEmitterPointer = eventEmitterPointer
  566. }
  567. public func getNextEvent() -> DcEvent? {
  568. guard let eventPointer = dc_accounts_get_next_event(eventEmitterPointer) else { return nil }
  569. return DcEvent(eventPointer: eventPointer)
  570. }
  571. deinit {
  572. dc_accounts_event_emitter_unref(eventEmitterPointer)
  573. }
  574. }
  575. public class DcEventEmitter {
  576. private var eventEmitterPointer: OpaquePointer?
  577. // takes ownership of specified pointer
  578. public init(eventEmitterPointer: OpaquePointer?) {
  579. self.eventEmitterPointer = eventEmitterPointer
  580. }
  581. public func getNextEvent() -> DcEvent? {
  582. guard let eventPointer = dc_get_next_event(eventEmitterPointer) else { return nil }
  583. return DcEvent(eventPointer: eventPointer)
  584. }
  585. deinit {
  586. dc_event_emitter_unref(eventEmitterPointer)
  587. }
  588. }
  589. public class DcEvent {
  590. private var eventPointer: OpaquePointer?
  591. // takes ownership of specified pointer
  592. public init(eventPointer: OpaquePointer?) {
  593. self.eventPointer = eventPointer
  594. }
  595. deinit {
  596. dc_event_unref(eventPointer)
  597. }
  598. public var accountId: Int {
  599. return Int(dc_event_get_account_id(eventPointer))
  600. }
  601. public var id: Int32 {
  602. return Int32(dc_event_get_id(eventPointer))
  603. }
  604. public var data1Int: Int {
  605. return Int(dc_event_get_data1_int(eventPointer))
  606. }
  607. public var data2Int: Int {
  608. return Int(dc_event_get_data2_int(eventPointer))
  609. }
  610. public var data2String: String {
  611. guard let cString = dc_event_get_data2_str(eventPointer) else { return "" }
  612. let swiftString = String(cString: cString)
  613. dc_str_unref(cString)
  614. return swiftString
  615. }
  616. }
  617. public class DcChatlist {
  618. private var chatListPointer: OpaquePointer?
  619. // takes ownership of specified pointer
  620. public init(chatListPointer: OpaquePointer?) {
  621. self.chatListPointer = chatListPointer
  622. }
  623. deinit {
  624. dc_chatlist_unref(chatListPointer)
  625. }
  626. public var length: Int {
  627. return dc_chatlist_get_cnt(chatListPointer)
  628. }
  629. public func getChatId(index: Int) -> Int {
  630. return Int(dc_chatlist_get_chat_id(chatListPointer, index))
  631. }
  632. public func getMsgId(index: Int) -> Int {
  633. return Int(dc_chatlist_get_msg_id(chatListPointer, index))
  634. }
  635. public func getSummary(index: Int) -> DcLot {
  636. guard let lotPointer = dc_chatlist_get_summary(self.chatListPointer, index, nil) else {
  637. fatalError("lot-pointer was nil")
  638. }
  639. return DcLot(lotPointer)
  640. }
  641. }
  642. public class DcChat {
  643. var chatPointer: OpaquePointer?
  644. // use DcContext.getChat() instead of calling the constructor directly
  645. public init(chatPointer: OpaquePointer?) {
  646. self.chatPointer = chatPointer
  647. }
  648. deinit {
  649. dc_chat_unref(chatPointer)
  650. }
  651. public var id: Int {
  652. return Int(dc_chat_get_id(chatPointer))
  653. }
  654. public var name: String {
  655. guard let cString = dc_chat_get_name(chatPointer) else { return "" }
  656. let swiftString = String(cString: cString)
  657. dc_str_unref(cString)
  658. return swiftString
  659. }
  660. public var color: UIColor {
  661. return UIColor(netHex: Int(dc_chat_get_color(chatPointer)))
  662. }
  663. public var isArchived: Bool {
  664. return Int(dc_chat_get_visibility(chatPointer)) == DC_CHAT_VISIBILITY_ARCHIVED
  665. }
  666. public var visibility: Int32 {
  667. return dc_chat_get_visibility(chatPointer)
  668. }
  669. public var isUnpromoted: Bool {
  670. return Int(dc_chat_is_unpromoted(chatPointer)) != 0
  671. }
  672. public var isGroup: Bool {
  673. // isMultiUser() might fit better,
  674. // however, would result in lots of code changes, so we leave this as is for now.
  675. let type = Int(dc_chat_get_type(chatPointer))
  676. return type == DC_CHAT_TYPE_GROUP || type == DC_CHAT_TYPE_MAILINGLIST
  677. }
  678. public var isMailinglist: Bool {
  679. return Int(dc_chat_get_type(chatPointer)) == DC_CHAT_TYPE_MAILINGLIST
  680. }
  681. public var isSelfTalk: Bool {
  682. return Int(dc_chat_is_self_talk(chatPointer)) != 0
  683. }
  684. public var isDeviceTalk: Bool {
  685. return Int(dc_chat_is_device_talk(chatPointer)) != 0
  686. }
  687. public var canSend: Bool {
  688. return Int(dc_chat_can_send(chatPointer)) != 0
  689. }
  690. public var isProtected: Bool {
  691. return dc_chat_is_protected(chatPointer) != 0
  692. }
  693. public var isMuted: Bool {
  694. return dc_chat_is_muted(chatPointer) != 0
  695. }
  696. public func getContactIds(_ dcContext: DcContext) -> [Int] {
  697. return DcUtils.copyAndFreeArray(inputArray: dc_get_chat_contacts(dcContext.contextPointer, UInt32(id)))
  698. }
  699. public lazy var profileImage: UIImage? = { [weak self] in
  700. guard let cString = dc_chat_get_profile_image(chatPointer) else { return nil }
  701. let filename = String(cString: cString)
  702. dc_str_unref(cString)
  703. let path: URL = URL(fileURLWithPath: filename, isDirectory: false)
  704. if path.isFileURL {
  705. do {
  706. let data = try Data(contentsOf: path)
  707. let image = UIImage(data: data)
  708. return image
  709. } catch {
  710. print("failed to load image: \(filename), \(error)")
  711. return nil
  712. }
  713. }
  714. return nil
  715. }()
  716. public var profileImageURL: URL? {
  717. guard let cString = dc_chat_get_profile_image(chatPointer) else { return nil }
  718. let filename = String(cString: cString)
  719. dc_str_unref(cString)
  720. let path: URL = URL(fileURLWithPath: filename, isDirectory: false)
  721. return path
  722. }
  723. public var isSendingLocations: Bool {
  724. return dc_chat_is_sending_locations(chatPointer) == 1
  725. }
  726. }
  727. public class DcArray {
  728. private var dcArrayPointer: OpaquePointer?
  729. public init(arrayPointer: OpaquePointer) {
  730. dcArrayPointer = arrayPointer
  731. }
  732. deinit {
  733. dc_array_unref(dcArrayPointer)
  734. }
  735. public var count: Int {
  736. return Int(dc_array_get_cnt(dcArrayPointer))
  737. }
  738. }
  739. public class DcMsg {
  740. var messagePointer: OpaquePointer?
  741. init(pointer: OpaquePointer?) {
  742. messagePointer = pointer
  743. }
  744. deinit {
  745. dc_msg_unref(messagePointer)
  746. }
  747. public var cptr: OpaquePointer? {
  748. return messagePointer
  749. }
  750. public lazy var sentDate: Date = {
  751. Date(timeIntervalSince1970: Double(timestamp))
  752. }()
  753. public func formattedSentDate() -> String {
  754. return DateUtils.getExtendedRelativeTimeSpanString(timeStamp: Double(timestamp))
  755. }
  756. public var isForwarded: Bool {
  757. return dc_msg_is_forwarded(messagePointer) != 0
  758. }
  759. public var messageId: String {
  760. return "\(id)"
  761. }
  762. public var id: Int {
  763. return Int(dc_msg_get_id(messagePointer))
  764. }
  765. public var fromContactId: Int {
  766. return Int(dc_msg_get_from_id(messagePointer))
  767. }
  768. public var isFromCurrentSender: Bool {
  769. return fromContactId == DC_CONTACT_ID_SELF
  770. }
  771. public var chatId: Int {
  772. return Int(dc_msg_get_chat_id(messagePointer))
  773. }
  774. public var realChatId: Int {
  775. return Int(dc_msg_get_real_chat_id(messagePointer))
  776. }
  777. public var overrideSenderName: String? {
  778. guard let cString = dc_msg_get_override_sender_name(messagePointer) else { return nil }
  779. let swiftString = String(cString: cString)
  780. dc_str_unref(cString)
  781. return swiftString
  782. }
  783. public func getSenderName(_ dcContact: DcContact, markOverride: Bool = false) -> String {
  784. if let overrideName = overrideSenderName {
  785. return (markOverride ? "~" : "") + overrideName
  786. } else {
  787. return dcContact.displayName
  788. }
  789. }
  790. public var text: String? {
  791. get {
  792. guard let cString = dc_msg_get_text(messagePointer) else { return nil }
  793. let swiftString = String(cString: cString)
  794. dc_str_unref(cString)
  795. return swiftString
  796. }
  797. set {
  798. if let newValue = newValue {
  799. dc_msg_set_text(messagePointer, newValue.cString(using: .utf8))
  800. } else {
  801. dc_msg_set_text(messagePointer, nil)
  802. }
  803. }
  804. }
  805. public var subject: String {
  806. guard let cString = dc_msg_get_subject(messagePointer) else { return "" }
  807. let swiftString = String(cString: cString)
  808. dc_str_unref(cString)
  809. return swiftString
  810. }
  811. public var quoteText: String? {
  812. guard let cString = dc_msg_get_quoted_text(messagePointer) else { return nil }
  813. let swiftString = String(cString: cString)
  814. dc_str_unref(cString)
  815. return swiftString
  816. }
  817. public var quoteMessage: DcMsg? {
  818. get {
  819. guard let msgpointer = dc_msg_get_quoted_msg(messagePointer) else { return nil }
  820. return DcMsg(pointer: msgpointer)
  821. }
  822. set {
  823. if newValue == nil {
  824. fatalError("Quote message cannot be set to null!")
  825. }
  826. dc_msg_set_quote(messagePointer, newValue?.messagePointer)
  827. }
  828. }
  829. public var viewtype: MessageViewType? {
  830. switch dc_msg_get_viewtype(messagePointer) {
  831. case 0:
  832. return nil
  833. case DC_MSG_AUDIO:
  834. return .audio
  835. case DC_MSG_FILE:
  836. return .file
  837. case DC_MSG_GIF:
  838. return .gif
  839. case DC_MSG_TEXT:
  840. return .text
  841. case DC_MSG_IMAGE:
  842. return .image
  843. case DC_MSG_STICKER:
  844. return .image
  845. case DC_MSG_VIDEO:
  846. return .video
  847. case DC_MSG_VOICE:
  848. return .voice
  849. default:
  850. return nil
  851. }
  852. }
  853. public var fileURL: URL? {
  854. if let file = self.file {
  855. return URL(fileURLWithPath: file, isDirectory: false)
  856. }
  857. return nil
  858. }
  859. public lazy var image: UIImage? = { [weak self] in
  860. let filetype = dc_msg_get_viewtype(messagePointer)
  861. if let path = fileURL, filetype == DC_MSG_IMAGE || filetype == DC_MSG_GIF || filetype == DC_MSG_STICKER {
  862. if path.isFileURL {
  863. do {
  864. let data = try Data(contentsOf: path)
  865. let image = UIImage(data: data)
  866. return image
  867. } catch {
  868. print("failed to load image: \(path), \(error)")
  869. return nil
  870. }
  871. }
  872. return nil
  873. } else {
  874. return nil
  875. }
  876. }()
  877. public var messageHeight: CGFloat {
  878. return CGFloat(dc_msg_get_height(messagePointer))
  879. }
  880. public var messageWidth: CGFloat {
  881. return CGFloat(dc_msg_get_width(messagePointer))
  882. }
  883. public var duration: Int {
  884. return Int(dc_msg_get_duration(messagePointer))
  885. }
  886. public func setLateFilingMediaSize(width: CGFloat, height: CGFloat, duration: Int) {
  887. dc_msg_latefiling_mediasize(messagePointer, Int32(width), Int32(height), Int32(duration))
  888. }
  889. public var file: String? {
  890. if let cString = dc_msg_get_file(messagePointer) {
  891. let str = String(cString: cString)
  892. dc_str_unref(cString)
  893. return str.isEmpty ? nil : str
  894. }
  895. return nil
  896. }
  897. public var filemime: String? {
  898. if let cString = dc_msg_get_filemime(messagePointer) {
  899. let str = String(cString: cString)
  900. dc_str_unref(cString)
  901. return str.isEmpty ? nil : str
  902. }
  903. return nil
  904. }
  905. public var filename: String? {
  906. if let cString = dc_msg_get_filename(messagePointer) {
  907. let str = String(cString: cString)
  908. dc_str_unref(cString)
  909. return str.isEmpty ? nil : str
  910. }
  911. return nil
  912. }
  913. public func setFile(filepath: String?, mimeType: String? = nil) {
  914. dc_msg_set_file(messagePointer, filepath, mimeType)
  915. }
  916. public func setDimension(width: CGFloat, height: CGFloat) {
  917. dc_msg_set_dimension(messagePointer, Int32(width), Int32(height))
  918. }
  919. public var filesize: Int {
  920. return Int(dc_msg_get_filebytes(messagePointer))
  921. }
  922. // DC_MSG_*
  923. public var type: Int {
  924. return Int(dc_msg_get_viewtype(messagePointer))
  925. }
  926. // DC_STATE_*
  927. public var state: Int {
  928. return Int(dc_msg_get_state(messagePointer))
  929. }
  930. public var timestamp: Int64 {
  931. return Int64(dc_msg_get_timestamp(messagePointer))
  932. }
  933. public var isInfo: Bool {
  934. return dc_msg_is_info(messagePointer) == 1
  935. }
  936. public var isSetupMessage: Bool {
  937. return dc_msg_is_setupmessage(messagePointer) == 1
  938. }
  939. public var hasHtml: Bool {
  940. return dc_msg_has_html(messagePointer) == 1
  941. }
  942. public var hasLocation: Bool {
  943. return dc_msg_has_location(messagePointer) == 1
  944. }
  945. public var setupCodeBegin: String {
  946. guard let cString = dc_msg_get_setupcodebegin(messagePointer) else { return "" }
  947. let swiftString = String(cString: cString)
  948. dc_str_unref(cString)
  949. return swiftString
  950. }
  951. public func summary(chars: Int) -> String? {
  952. guard let cString = dc_msg_get_summarytext(messagePointer, Int32(chars)) else { return nil }
  953. let swiftString = String(cString: cString)
  954. dc_str_unref(cString)
  955. return swiftString
  956. }
  957. public func summary(chat: DcChat) -> DcLot {
  958. guard let chatPointer = chat.chatPointer else {
  959. fatalError()
  960. }
  961. guard let dcLotPointer = dc_msg_get_summary(messagePointer, chatPointer) else {
  962. fatalError()
  963. }
  964. return DcLot(dcLotPointer)
  965. }
  966. public func showPadlock() -> Bool {
  967. return dc_msg_get_showpadlock(messagePointer) == 1
  968. }
  969. }
  970. public class DcContact {
  971. private var contactPointer: OpaquePointer?
  972. public init(contactPointer: OpaquePointer?) {
  973. self.contactPointer = contactPointer
  974. }
  975. deinit {
  976. dc_contact_unref(contactPointer)
  977. }
  978. public var displayName: String {
  979. guard let cString = dc_contact_get_display_name(contactPointer) else { return "" }
  980. let swiftString = String(cString: cString)
  981. dc_str_unref(cString)
  982. return swiftString
  983. }
  984. public var nameNAddr: String {
  985. guard let cString = dc_contact_get_name_n_addr(contactPointer) else { return "" }
  986. let swiftString = String(cString: cString)
  987. dc_str_unref(cString)
  988. return swiftString
  989. }
  990. public var editedName: String {
  991. guard let cString = dc_contact_get_name(contactPointer) else { return "" }
  992. let swiftString = String(cString: cString)
  993. dc_str_unref(cString)
  994. return swiftString
  995. }
  996. public var authName: String {
  997. guard let cString = dc_contact_get_auth_name(contactPointer) else { return "" }
  998. let swiftString = String(cString: cString)
  999. dc_str_unref(cString)
  1000. return swiftString
  1001. }
  1002. public var email: String {
  1003. guard let cString = dc_contact_get_addr(contactPointer) else { return "" }
  1004. let swiftString = String(cString: cString)
  1005. dc_str_unref(cString)
  1006. return swiftString
  1007. }
  1008. public var status: String {
  1009. guard let cString = dc_contact_get_status(contactPointer) else { return "" }
  1010. let swiftString = String(cString: cString)
  1011. dc_str_unref(cString)
  1012. return swiftString
  1013. }
  1014. public var isVerified: Bool {
  1015. return dc_contact_is_verified(contactPointer) > 0
  1016. }
  1017. public var isBlocked: Bool {
  1018. return dc_contact_is_blocked(contactPointer) == 1
  1019. }
  1020. public lazy var profileImage: UIImage? = { [weak self] in
  1021. guard let cString = dc_contact_get_profile_image(contactPointer) else { return nil }
  1022. let filename = String(cString: cString)
  1023. dc_str_unref(cString)
  1024. let path: URL = URL(fileURLWithPath: filename, isDirectory: false)
  1025. if path.isFileURL {
  1026. do {
  1027. let data = try Data(contentsOf: path)
  1028. return UIImage(data: data)
  1029. } catch {
  1030. print("failed to load image: \(filename), \(error)")
  1031. return nil
  1032. }
  1033. }
  1034. return nil
  1035. }()
  1036. public var profileImageURL: URL? {
  1037. guard let cString = dc_contact_get_profile_image(contactPointer) else { return nil }
  1038. let filename = String(cString: cString)
  1039. dc_str_unref(cString)
  1040. return URL(fileURLWithPath: filename, isDirectory: false)
  1041. }
  1042. public var color: UIColor {
  1043. return UIColor(netHex: Int(dc_contact_get_color(contactPointer)))
  1044. }
  1045. public var id: Int {
  1046. return Int(dc_contact_get_id(contactPointer))
  1047. }
  1048. }
  1049. public class DcLot {
  1050. private var dcLotPointer: OpaquePointer?
  1051. // takes ownership of specified pointer
  1052. public init(_ dcLotPointer: OpaquePointer) {
  1053. self.dcLotPointer = dcLotPointer
  1054. }
  1055. deinit {
  1056. dc_lot_unref(dcLotPointer)
  1057. }
  1058. public var text1: String? {
  1059. guard let cString = dc_lot_get_text1(dcLotPointer) else { return nil }
  1060. let swiftString = String(cString: cString)
  1061. dc_str_unref(cString)
  1062. return swiftString
  1063. }
  1064. public var text1Meaning: Int {
  1065. return Int(dc_lot_get_text1_meaning(dcLotPointer))
  1066. }
  1067. public var text2: String? {
  1068. guard let cString = dc_lot_get_text2(dcLotPointer) else { return nil }
  1069. let swiftString = String(cString: cString)
  1070. dc_str_unref(cString)
  1071. return swiftString
  1072. }
  1073. public var timestamp: Int64 {
  1074. return Int64(dc_lot_get_timestamp(dcLotPointer))
  1075. }
  1076. public var state: Int {
  1077. return Int(dc_lot_get_state(dcLotPointer))
  1078. }
  1079. public var id: Int {
  1080. return Int(dc_lot_get_id(dcLotPointer))
  1081. }
  1082. }
  1083. public class DcProvider {
  1084. private var dcProviderPointer: OpaquePointer?
  1085. // takes ownership of specified pointer
  1086. public init(_ dcProviderPointer: OpaquePointer) {
  1087. self.dcProviderPointer = dcProviderPointer
  1088. }
  1089. deinit {
  1090. dc_provider_unref(dcProviderPointer)
  1091. }
  1092. public var status: Int {
  1093. return Int(dc_provider_get_status(dcProviderPointer))
  1094. }
  1095. public var beforeLoginHint: String {
  1096. guard let cString = dc_provider_get_before_login_hint(dcProviderPointer) else { return "" }
  1097. let swiftString = String(cString: cString)
  1098. dc_str_unref(cString)
  1099. return swiftString
  1100. }
  1101. public var getOverviewPage: String {
  1102. guard let cString = dc_provider_get_overview_page(dcProviderPointer) else { return "" }
  1103. let swiftString = String(cString: cString)
  1104. dc_str_unref(cString)
  1105. return swiftString
  1106. }
  1107. }
  1108. public enum MessageViewType: CustomStringConvertible {
  1109. case audio
  1110. case file
  1111. case gif
  1112. case image
  1113. case text
  1114. case video
  1115. case voice
  1116. public var description: String {
  1117. switch self {
  1118. // Use Internationalization, as appropriate.
  1119. case .audio: return "Audio"
  1120. case .file: return "File"
  1121. case .gif: return "GIF"
  1122. case .image: return "Image"
  1123. case .text: return "Text"
  1124. case .video: return "Video"
  1125. case .voice: return "Voice"
  1126. }
  1127. }
  1128. }
  1129. func strToBool(_ value: String?) -> Bool {
  1130. if let vStr = value {
  1131. if let vInt = Int(vStr) {
  1132. return vInt == 1
  1133. }
  1134. return false
  1135. }
  1136. return false
  1137. }