Browse Source

update and release for 5.0.66

alqindiirsyam 1 tuần trước cách đây
mục cha
commit
cf188a2f57

+ 4 - 4
AppBuilder/AppBuilder.xcodeproj/project.pbxproj

@@ -568,7 +568,7 @@
 					"$(inherited)",
 					"@executable_path/Frameworks",
 				);
-				MARKETING_VERSION = 5.0.64;
+				MARKETING_VERSION = 5.0.66;
 				PRODUCT_BUNDLE_IDENTIFIER = io.nexilis.appbuilder;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PROVISIONING_PROFILE_SPECIFIER = "";
@@ -604,7 +604,7 @@
 					"$(inherited)",
 					"@executable_path/Frameworks",
 				);
-				MARKETING_VERSION = 5.0.64;
+				MARKETING_VERSION = 5.0.66;
 				PRODUCT_BUNDLE_IDENTIFIER = io.nexilis.appbuilder;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				PROVISIONING_PROFILE_SPECIFIER = "";
@@ -640,7 +640,7 @@
 					"@executable_path/../../Frameworks",
 				);
 				LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
-				MARKETING_VERSION = 5.0.64;
+				MARKETING_VERSION = 5.0.66;
 				OTHER_CFLAGS = "-fstack-protector-strong";
 				PRODUCT_BUNDLE_IDENTIFIER = io.nexilis.appbuilder.AppBuilderShare;
 				PRODUCT_NAME = "$(TARGET_NAME)";
@@ -679,7 +679,7 @@
 					"@executable_path/../../Frameworks",
 				);
 				LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
-				MARKETING_VERSION = 5.0.64;
+				MARKETING_VERSION = 5.0.66;
 				OTHER_CFLAGS = "-fstack-protector-strong";
 				PRODUCT_BUNDLE_IDENTIFIER = io.nexilis.appbuilder.AppBuilderShare;
 				PRODUCT_NAME = "$(TARGET_NAME)";

+ 6 - 6
AppBuilder/AppBuilder/FourthTabViewController.swift

@@ -944,12 +944,12 @@ public class FourthTabViewController: UIViewController, UITableViewDelegate, UIT
                                 Utils.setLastTabSelected(value: 0)
                                 Utils.setIsWATheme(value: false)
                                 UIApplication.shared.setAlternateIconName(nil)
-                                Database.shared.database?.inTransaction({ fmdb, rollback in
-                                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "GROUPZ", _where: "")
-                                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "GROUPZ_MEMBER", _where: "")
-                                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "DISCUSSION_FORUM", _where: "")
-                                    _ = Nexilis.write(message: CoreMessage_TMessageBank.getPostRegistration(p_pin: User.getMyPin() ?? ""))
-                                })
+//                                Database.shared.database?.inTransaction({ fmdb, rollback in
+//                                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "GROUPZ", _where: "")
+//                                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "GROUPZ_MEMBER", _where: "")
+//                                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "DISCUSSION_FORUM", _where: "")
+//                                    _ = Nexilis.write(message: CoreMessage_TMessageBank.getPostRegistration(p_pin: User.getMyPin() ?? ""))
+//                                })
                                 Nexilis.hideLoader {
                                     let alert = LibAlertController(title: "Successfully changed".localized(), message: "Please open the app again to see the changes".localized(), preferredStyle: .alert)
                                     alert.addAction(UIAlertAction(title: "OK".localized(), style: .default, handler: {(_) in

+ 2 - 2
AppBuilder/AppBuilder/SecondTabViewController.swift

@@ -2222,7 +2222,7 @@ extension SecondTabViewController: UITableViewDelegate, UITableViewDataSource {
                             stringMessage.append(("🚫 _"+"You were deleted this message".localized()+"_").richText())
                         } else {
                             let imageStatus = NSTextAttachment()
-                            if data.messageScope != MessageScope.CALL && data.messageScope != MessageScope.MISSED_CALL && !data.messageId.contains("NTFPIN_") {
+                            if data.messageScope != MessageScope.CALL && data.messageScope != MessageScope.MISSED_CALL && !data.messageId.contains("NTFPIN_") && data.messageScope != MessageScope.GPT_CHATBOT {
                                 let status = getRealStatus(messageId: data.messageId)
                                 if status == "0" {
                                     imageStatus.image = UIImage(systemName: "xmark.circle")!.withTintColor(UIColor.red, renderingMode: .alwaysOriginal)
@@ -2257,7 +2257,7 @@ extension SecondTabViewController: UITableViewDelegate, UITableViewDataSource {
                             stringMessage.append(NSAttributedString(string: fullname + ": ", attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 12 + String.offset(), weight: .medium)]))
                         }
                         if data.messageScope == MessageScope.WHISPER && data.isBot == 1 {
-                            stringMessage.append(NSAttributedString(string: "GPT SmartBot" + ": ", attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 12 + String.offset(), weight: .medium)]))
+                            stringMessage.append(NSAttributedString(string: Utils.getGPTBotName() + ": ", attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 12 + String.offset(), weight: .medium)]))
                         }
                         if data.lock == "1" {
                             stringMessage.append(("🚫 _"+"This message was deleted".localized()+"_").richText())

+ 100 - 52
NexilisLite/NexilisLite/Source/APIS.swift

@@ -840,7 +840,7 @@ public class APIS: NSObject {
                                 }
                             }
 //                            let secret = "JBSWY3DPEHPK3PXP" // Google Authenticator example
-                            let otp = try TOTPGenerator.generateTOTP(base32Secret: TOTPGenerator.getTOTP(), digits: 6, timeStepSeconds: 30)
+                            let otp = try TOTPGenerator.generateTOTP(base32Secret: TOTPGenerator.getTOTP(), digits: 6, timeStepSeconds: 300)
                             message.mBodies[CoreMessage_TMessageKey.TOTP] = otp
                             if let response = Nexilis.writeAndWait(message: message) {
                                 if response.isOk() {
@@ -1734,61 +1734,37 @@ public class APIS: NSObject {
     }
     
     private static func getMessageById(id: String, retry: Int = 0, completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
-        let parameter: [String : Any] = [
-            "pin": User.getMyPin() ?? "",
-            "message_id": id
-        ]
-        Utils.postDataWithCookiesAndUserAgent(from: URL(string: Utils.getDomainOpr() + "pull_notification")!, parameter: parameter, isFormData: true) { data, response, error in
-            if error != nil {
-                let ret = retry + 1
-                if ret <= 5 {
-                    getMessageById(id: id, retry: ret, completionHandler: completionHandler)
-                } else {
-                    completionHandler(.failed)
-                }
-            } else if let data = data {
-                do {
-                    if let dataString = String(data: data, encoding: .utf8) {
-                        if let jsonObj = try JSONSerialization.jsonObject(with: dataString.data(using: String.Encoding.utf8)!, options: JSONSerialization.ReadingOptions()) as? [String: Any] {
-                            let dataObj = jsonObj["data"] as? String ?? ""
-                            let message = TMessage(data: dataObj)
-                            if Utils.getSecureFolderOffline() == "0" && IncomingThread.dispatch == nil {
-                                if API.nGetCLXConnState() == 0 {
-                                    do {
-                                        let id = Utils.getConnectionID()
-                                        try API.initConnection(sAPIK: Nexilis.sAPIKey, cbiI: Callback(), sTCPAddr: Nexilis.ADDRESS, nTCPPort: Nexilis.PORT, sUserID: id, sStartWH: "09:00")
-                                    } catch {}
-                                }
-                                if FileEncryption.shared.aesKey == nil {
-                                    IncomingThread.dispatch = DispatchGroup()
-                                    IncomingThread.dispatch?.enter()
-                                    Nexilis.getFeatureAccess()
-                                    IncomingThread.dispatch?.wait()
-                                    IncomingThread.dispatch = nil
-                                }
+        if API.nGetCLXConnState() == 0 {
+            do {
+                let id = Utils.getConnectionID()
+                try API.initConnection(sAPIK: Nexilis.sAPIKey, cbiI: Callback(), sTCPAddr: Nexilis.ADDRESS, nTCPPort: Nexilis.PORT, sUserID: id, sStartWH: "09:00")
+            } catch {}
+        }
+        while API.nGetCLXConnState() == 0 {
+            Thread.sleep(forTimeInterval: 0.5)
+        }
+        if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getMessageById(messageId: id), timeout: 30000) {
+            if response.isOk() {
+                let data = response.getBody(key: CoreMessage_TMessageKey.DATA)
+                if let decodedData = Data(base64Encoded: data, options: .ignoreUnknownCharacters) {
+                    if let respData = String(data: decodedData, encoding: .utf8) {
+                        let message = TMessage(data: respData)
+                        if Utils.getSecureFolderOffline() == "0" && IncomingThread.dispatch == nil {
+                            if FileEncryption.shared.aesKey == nil {
+                                IncomingThread.dispatch = DispatchGroup()
+                                IncomingThread.dispatch?.enter()
+                                Nexilis.getFeatureAccess()
+                                IncomingThread.dispatch?.wait()
+                                IncomingThread.dispatch = nil
                             }
+                        }
 //                                print("save from APIS")
-                            Nexilis.saveMessage(message: message, withStatus: false, fromAPNS: true)
-                            ackAPN(id: id)
-                            DispatchQueue.main.async {
-                                UIApplication.shared.applicationIconBadgeNumber = Int(APIS.getTotalCounter())
-                            }
-                        } else {
-                            let ret = retry + 1
-                            if ret <= 5 {
-                                getMessageById(id: id, retry: ret, completionHandler: completionHandler)
-                            } else {
-                                completionHandler(.failed)
-                            }
+                        Nexilis.saveMessage(message: message, withStatus: false, fromAPNS: true)
+                        ackAPN(id: id)
+                        DispatchQueue.main.async {
+                            UIApplication.shared.applicationIconBadgeNumber = Int(APIS.getTotalCounter())
                         }
                     }
-                } catch {
-                    let ret = retry + 1
-                    if ret <= 5 {
-                        getMessageById(id: id, retry: ret, completionHandler: completionHandler)
-                    } else {
-                        completionHandler(.failed)
-                    }
                 }
             } else {
                 let ret = retry + 1
@@ -1798,7 +1774,79 @@ public class APIS: NSObject {
                     completionHandler(.failed)
                 }
             }
+        } else {
+            let ret = retry + 1
+            if ret <= 5 {
+                getMessageById(id: id, retry: ret, completionHandler: completionHandler)
+            } else {
+                completionHandler(.failed)
+            }
         }
+//        let parameter: [String : Any] = [
+//            "pin": User.getMyPin() ?? "",
+//            "message_id": id
+//        ]
+//        Utils.postDataWithCookiesAndUserAgent(from: URL(string: Utils.getDomainOpr() + "pull_notification")!, parameter: parameter, isFormData: true) { data, response, error in
+//            if error != nil {
+//                let ret = retry + 1
+//                if ret <= 5 {
+//                    getMessageById(id: id, retry: ret, completionHandler: completionHandler)
+//                } else {
+//                    completionHandler(.failed)
+//                }
+//            } else if let data = data {
+//                do {
+//                    if let dataString = String(data: data, encoding: .utf8) {
+//                        if let jsonObj = try JSONSerialization.jsonObject(with: dataString.data(using: String.Encoding.utf8)!, options: JSONSerialization.ReadingOptions()) as? [String: Any] {
+//                            let dataObj = jsonObj["data"] as? String ?? ""
+//                            let message = TMessage(data: dataObj)
+//                            if Utils.getSecureFolderOffline() == "0" && IncomingThread.dispatch == nil {
+//                                if API.nGetCLXConnState() == 0 {
+//                                    do {
+//                                        let id = Utils.getConnectionID()
+//                                        try API.initConnection(sAPIK: Nexilis.sAPIKey, cbiI: Callback(), sTCPAddr: Nexilis.ADDRESS, nTCPPort: Nexilis.PORT, sUserID: id, sStartWH: "09:00")
+//                                    } catch {}
+//                                }
+//                                if FileEncryption.shared.aesKey == nil {
+//                                    IncomingThread.dispatch = DispatchGroup()
+//                                    IncomingThread.dispatch?.enter()
+//                                    Nexilis.getFeatureAccess()
+//                                    IncomingThread.dispatch?.wait()
+//                                    IncomingThread.dispatch = nil
+//                                }
+//                            }
+////                                print("save from APIS")
+//                            Nexilis.saveMessage(message: message, withStatus: false, fromAPNS: true)
+//                            ackAPN(id: id)
+//                            DispatchQueue.main.async {
+//                                UIApplication.shared.applicationIconBadgeNumber = Int(APIS.getTotalCounter())
+//                            }
+//                        } else {
+//                            let ret = retry + 1
+//                            if ret <= 5 {
+//                                getMessageById(id: id, retry: ret, completionHandler: completionHandler)
+//                            } else {
+//                                completionHandler(.failed)
+//                            }
+//                        }
+//                    }
+//                } catch {
+//                    let ret = retry + 1
+//                    if ret <= 5 {
+//                        getMessageById(id: id, retry: ret, completionHandler: completionHandler)
+//                    } else {
+//                        completionHandler(.failed)
+//                    }
+//                }
+//            } else {
+//                let ret = retry + 1
+//                if ret <= 5 {
+//                    getMessageById(id: id, retry: ret, completionHandler: completionHandler)
+//                } else {
+//                    completionHandler(.failed)
+//                }
+//            }
+//        }
     }
     
     public static func addNotificationNexilis(_ message: TMessage) {

+ 2 - 2
NexilisLite/NexilisLite/Source/Model/Group.swift

@@ -181,7 +181,7 @@ public class Member: User {
                     }
                     if f_pin == "-997" {
                         member = Member(pin: "-997",
-                                        firstName: "GPT SmartBot",
+                                        firstName: Utils.getGPTBotName(),
                                         lastName: "",
                                         thumb: "",
                                         position: "")
@@ -210,7 +210,7 @@ public class Member: User {
                     }
                     if f_pin == "-997" {
                         member = Member(pin: "-997",
-                                        firstName: "GPT SmartBot",
+                                        firstName: Utils.getGPTBotName(),
                                         lastName: "",
                                         thumb: "",
                                         position: "")

+ 8 - 1
NexilisLite/NexilisLite/Source/Model/User.swift

@@ -173,7 +173,7 @@ public class User: Model {
                             ex_block: "")
             } else if pin == "-997" {
                 user = User(pin: "-997",
-                            firstName: "GPT SmartBot",
+                            firstName: Utils.getGPTBotName(),
                             lastName: "",
                             thumb: "",
                             userType: "0",
@@ -225,6 +225,13 @@ public class User: Model {
                                     privacy_flag: "",
                                     offline_mode: "",
                                     ex_block: "")
+                    } else if pin == "-997" {
+                        user = User(pin: "-997",
+                                    firstName: Utils.getGPTBotName(),
+                                    lastName: "",
+                                    thumb: "",
+                                    userType: "0",
+                                    official: "1")
                     } else {
                         user = User(pin: pin,
                                     firstName: "User".localized(),

+ 4 - 2
NexilisLite/NexilisLite/Source/Nexilis.swift

@@ -19,7 +19,7 @@ import CryptoKit
 import WebKit
 
 public class Nexilis: NSObject {
-    public static var cpaasVersion = "5.0.65"
+    public static var cpaasVersion = "5.0.66"
     public static var sAPIKey = ""
     
     public static var ADDRESS = ""
@@ -1732,8 +1732,10 @@ public class Nexilis: NSObject {
                 if is_call_center == "0" {
                     do {
                         var queryGetLastMessageId = "SELECT message_id FROM MESSAGE where (f_pin = '\(pin)' OR l_pin = '\(pin)') AND message_scope_id = '\(MessageScope.WHISPER)' order by server_date desc LIMIT 1"
-                        if scope == "4" {
+                        if scope == MessageScope.GROUP {
                             queryGetLastMessageId = "SELECT message_id FROM MESSAGE where l_pin = '\(chat_id.isEmpty ? pin : l_pin)' AND chat_id = '\(chat_id)' AND message_scope_id = '\(MessageScope.GROUP)' order by server_date desc LIMIT 1"
+                        } else if scope == MessageScope.GPT_CHATBOT {
+                            queryGetLastMessageId = "SELECT message_id FROM MESSAGE where (f_pin = '\(pin)' OR l_pin = '\(pin)') AND message_scope_id = '\(MessageScope.GPT_CHATBOT)' order by server_date desc LIMIT 1"
                         }
                         var messageId = ""
                         var pinned = 0

+ 12 - 0
NexilisLite/NexilisLite/Source/Utils.swift

@@ -947,6 +947,9 @@ public final class Utils {
                     if Array(json.keys)[i] == "gptbot_url" {
                         Utils.setGPTBotUrl(value: Array(json.values)[i] as? String ?? "")
                     }
+                    if Array(json.keys)[i] == "gptbot_name" {
+                        Utils.setGPTBotName(value: Array(json.values)[i] as? String ?? "")
+                    }
                     if Array(json.keys)[i] == "default_sound_incmsg" {
                         Utils.setDefaultIncomingMsg(value: Array(json.values)[i] as? String ?? "")
                     }
@@ -1441,6 +1444,15 @@ public final class Utils {
         }
         return Utils.decrypt(str: "3wsj<B67B=rl;vlol0hq<<=vswwk")
     }
+    public static func setGPTBotName(value: String) {
+        SecureUserDefaults.shared.set(value, forKey: "gptbot_name")
+    }
+    public static func getGPTBotName() -> String {
+        if let value: String = SecureUserDefaults.shared.value(forKey: "gptbot_name") {
+            return value
+        }
+        return "GPT SmartBot"
+    }
     static func setDebugBC(value: [String: String]) {
         SecureUserDefaults.shared.set(value, forKey: "debugBc")
     }

+ 11 - 11
NexilisLite/NexilisLite/Source/View/BNIView/BNIBookingWebView.swift

@@ -549,17 +549,17 @@ public class BNIBookingWebView: UIViewController, WKNavigationDelegate, UIScroll
                 } catch {
                 }
             }
-            Database.shared.database?.inTransaction({ fmdb, rollback in
-                do {
-                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "GROUPZ", _where: "")
-                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "GROUPZ_MEMBER", _where: "")
-                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "DISCUSSION_FORUM", _where: "")
-                    _ = Nexilis.write(message: CoreMessage_TMessageBank.getPostRegistration(p_pin: User.getMyPin() ?? ""))
-                } catch {
-                    rollback.pointee = true
-                    print("Access database error: \(error.localizedDescription)")
-                }
-            })
+//            Database.shared.database?.inTransaction({ fmdb, rollback in
+//                do {
+//                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "GROUPZ", _where: "")
+//                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "GROUPZ_MEMBER", _where: "")
+//                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "DISCUSSION_FORUM", _where: "")
+//                    _ = Nexilis.write(message: CoreMessage_TMessageBank.getPostRegistration(p_pin: User.getMyPin() ?? ""))
+//                } catch {
+//                    rollback.pointee = true
+//                    print("Access database error: \(error.localizedDescription)")
+//                }
+//            })
             let alert = LibAlertController(title: "Successfully changed".localized(), message: "Please open the app again to see the changes".localized(), preferredStyle: .alert)
             alert.addAction(UIAlertAction(title: "OK".localized(), style: .default, handler: {(_) in
                 exit(0)

+ 4 - 1
NexilisLite/NexilisLite/Source/View/Chat/ArchivedChatView.swift

@@ -360,7 +360,7 @@ public class ArchivedChatView: UIViewController, UITableViewDataSource, UITableV
                         stringMessage.append(("🚫 _"+"You were deleted this message".localized()+"_").richText())
                     } else {
                         let imageStatus = NSTextAttachment()
-                        if data.messageScope != MessageScope.CALL && data.messageScope != MessageScope.MISSED_CALL {
+                        if data.messageScope != MessageScope.CALL && data.messageScope != MessageScope.MISSED_CALL && data.messageScope != MessageScope.GPT_CHATBOT {
                             let status = getRealStatus(messageId: data.messageId)
                             if status == "0" {
                                 imageStatus.image = UIImage(systemName: "xmark.circle")!.withTintColor(UIColor.red, renderingMode: .alwaysOriginal)
@@ -394,6 +394,9 @@ public class ArchivedChatView: UIViewController, UITableViewDataSource, UITableV
                         }
                         stringMessage.append(NSAttributedString(string: fullname + ": ", attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 12 + String.offset(), weight: .medium)]))
                     }
+                    if data.messageScope == MessageScope.WHISPER && data.isBot == 1 {
+                        stringMessage.append(NSAttributedString(string: Utils.getGPTBotName() + ": ", attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 12 + String.offset(), weight: .medium)]))
+                    }
                     if data.lock == "1" {
                         stringMessage.append(("🚫 _"+"This message was deleted".localized()+"_").richText())
                     } else {

+ 12 - 32
NexilisLite/NexilisLite/Source/View/Chat/ChatGPTBotView.swift

@@ -13,12 +13,12 @@ import nuSDKService
 public class ChatGPTBotView: UIViewController, UIGestureRecognizerDelegate {
     public var dataPerson : [String: String?] = [
         "f_pin" : "-997",
-        "firstName" : "GPT SmartBot",
+        "firstName" : Utils.getGPTBotName(),
         "picture" : ""
     ]
     var dataMessages: [[String: Any?]] = []
     var dataDates: [String] = []
-    var chatGPTMessages: [[String: String]] = []
+    var chatGPTMessages: [[String: Any?]] = []
     
     @IBOutlet var tableChatView: UITableView!
     @IBOutlet var viewTextField: UIView!
@@ -118,7 +118,7 @@ public class ChatGPTBotView: UIViewController, UIGestureRecognizerDelegate {
     
     public override func viewDidLoad() {
         super.viewDidLoad()
-        navigationController?.navigationBar.topItem?.title = "GPT SmartBot"
+        navigationController?.navigationBar.topItem?.title = Utils.getGPTBotName()
         if Nexilis.fromMAB {
             Nexilis.floatingButton.isHidden = true
         }
@@ -189,7 +189,7 @@ public class ChatGPTBotView: UIViewController, UIGestureRecognizerDelegate {
                 _ = try Database.shared.insertRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
                     "message_id" : message_id ,
                     "f_pin" : "-997",
-                    "f_display_name" : "GPT SmartBot",
+                    "f_display_name" : Utils.getGPTBotName(),
                     "l_pin" : me,
                     "l_user_id" : String(user_id!),
                     "message_scope_id" : "31",
@@ -369,7 +369,7 @@ public class ChatGPTBotView: UIViewController, UIGestureRecognizerDelegate {
             self.tableChatView.endUpdates()
         }
         var gptRow : [String: String] = [:]
-        gptRow["role"] = row["f_pin"] as! String == "-997" ? "assistant" : "user"
+        gptRow["role"] = "user"
         gptRow["content"] = row["message_text"] as? String
         chatGPTMessages.append(gptRow)
         request(mesage: row["message_text"] as! String)
@@ -390,17 +390,15 @@ public class ChatGPTBotView: UIViewController, UIGestureRecognizerDelegate {
         }
         DispatchQueue.global().async {
             do {
-                if let response = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.requestGPTBot(message: mesage)) {
+                if let response = Nexilis.writeAndWait(message: CoreMessage_TMessageBank.requestGPTBot(message: mesage), timeout: 30000) {
                     if response.isOk() {
                         let data = response.getBody(key: CoreMessage_TMessageKey.DATA)
                         if let json = try! JSONSerialization.jsonObject(with: data.data(using: String.Encoding.utf8)!, options: []) as? [String: Any?] {
                             DispatchQueue.main.async {
                                 self.dataMessages.removeAll(where: { $0["is_loading"] as? Bool == true })
                                 self.tableChatView.reloadData()
-                                var gptRow : [String: String] = [:]
-                                gptRow["role"] = json["role"] as? String
-                                gptRow["content"] = json["content"] as? String
-                                self.chatGPTMessages.append(gptRow)
+                                self.chatGPTMessages.append(json)
+                                print("HOHO: \(json)")
                                 guard let me = User.getMyPin() else {
                                     return
                                 }
@@ -425,13 +423,13 @@ public class ChatGPTBotView: UIViewController, UIGestureRecognizerDelegate {
                                         _ = try Database.shared.insertRecord(fmdb: fmdb, table: "MESSAGE", cvalues: [
                                             "message_id" : message_id ,
                                             "f_pin" : "-997",
-                                            "f_display_name" : "GPT SmartBot",
+                                            "f_display_name" : Utils.getGPTBotName(),
                                             "l_pin" : me,
                                             "l_user_id" : String(user_id!),
                                             "message_scope_id" : "31",
                                             "server_date" : server_date,
                                             "status" : "3",
-                                            "message_text" : gptRow["content"],
+                                            "message_text" : json["content"],
                                             "audio_id" : "",
                                             "video_id" : "",
                                             "image_id" : "",
@@ -483,7 +481,7 @@ public class ChatGPTBotView: UIViewController, UIGestureRecognizerDelegate {
                                 row["message_scope_id"] = "31"
                                 row["server_date"] = server_date
                                 row["status"] = "3"
-                                row["message_text"] = gptRow["content"]
+                                row["message_text"] = json["content"]
                                 row["audio_id"] = ""
                                 row["video_id"] = ""
                                 row["image_id"] = ""
@@ -593,7 +591,7 @@ public class ChatGPTBotView: UIViewController, UIGestureRecognizerDelegate {
             }
             let titleNavigation = UILabel(frame: CGRect(x: 35, y: 0, width: viewAppBar.frame.size.width - 250, height: 44))
             viewAppBar.addSubview(titleNavigation)
-            titleNavigation.text = "GPT SmartBot"
+            titleNavigation.text = Utils.getGPTBotName()
             titleNavigation.textColor = .white
             titleNavigation.font = UIFont.systemFont(ofSize: 12 + offset()).bold
             
@@ -1852,24 +1850,6 @@ extension ChatGPTBotView: UITableViewDelegate, UITableViewDataSource {
             
             timeMessage.trailingAnchor.constraint(equalTo: containerMessage.leadingAnchor, constant: -8).isActive = true
             
-            if (dataMessages[indexPath.row]["lock"] == nil || dataMessages[indexPath.row]["lock"] as! String == "0") && (dataMessages[indexPath.row]["lock"] as? String != "2") {
-                cell.contentView.addSubview(statusMessage)
-                statusMessage.translatesAutoresizingMaskIntoConstraints = false
-                statusMessage.bottomAnchor.constraint(equalTo: timeMessage.topAnchor).isActive = true
-                statusMessage.trailingAnchor.constraint(equalTo: containerMessage.leadingAnchor, constant: -8).isActive = true
-                statusMessage.widthAnchor.constraint(equalToConstant: 15).isActive = true
-                statusMessage.heightAnchor.constraint(equalToConstant: 15).isActive = true
-                if (dataMessages[indexPath.row]["status"]! as! String == "1" || dataMessages[indexPath.row]["status"]! as! String == "2" ) {
-                    statusMessage.image = UIImage(named: "checklist", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withTintColor(UIColor.lightGray)
-                } else if (dataMessages[indexPath.row]["status"]! as! String == "3") {
-                    statusMessage.image = UIImage(named: "double-checklist", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withTintColor(UIColor.lightGray)
-                } else if (dataMessages[indexPath.row]["status"]! as! String == "8") {
-                    statusMessage.image = UIImage(named: "message_status_ack", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withRenderingMode(.alwaysOriginal)
-                } else {
-                    statusMessage.image = UIImage(named: "double-checklist", in: Bundle.resourceBundle(for: Nexilis.self), with: nil)!.withTintColor(UIColor.systemBlue)
-                }
-            }
-            
         } else {
             if markerCounter != nil && dataMessages[indexPath.row]["message_id"] as? String == markerCounter {
                 containerMessage.topAnchor.constraint(equalTo: cell.contentView.topAnchor, constant: 35).isActive = true

+ 29 - 17
NexilisLite/NexilisLite/Source/View/Chat/ChatWALikeVC.swift

@@ -52,6 +52,7 @@ public class ChatWALikeVC: UIViewController, UITableViewDataSource, UITableViewD
     var archivedChats: [Chat] = []
     var listMaxArchived: [String: [String]] = [:]
     var isGettingData = false
+    var timerReloadData: Timer?
     
     public override func viewDidLoad() {
         NotificationCenter.default.addObserver(self, selector: #selector(onStatusChat(notification:)), name: NSNotification.Name(rawValue: Nexilis.listenerStatusChat), object: nil)
@@ -79,11 +80,7 @@ public class ChatWALikeVC: UIViewController, UITableViewDataSource, UITableViewD
     }
     
     @objc func onDatabaseOpened(notification: NSNotification) {
-        DispatchQueue.main.async {
-            if self.loadingData {
-                self.refresh()
-            }
-        }
+        reloadAllData()
     }
     
     @objc func onDisconnected(notification: NSNotification) {
@@ -92,36 +89,48 @@ public class ChatWALikeVC: UIViewController, UITableViewDataSource, UITableViewD
             self.chatGroupMaps.removeAll()
             self.chats.removeAll()
             self.tableView.reloadData()
-            self.refresh()
+            self.reloadAllData()
         }
     }
     
     @objc func onReloadTab(notification: NSNotification) {
-        DispatchQueue.main.async {
-            self.refresh()
-        }
+        reloadAllData()
     }
     
     @objc func onReload(notification: NSNotification) {
         DispatchQueue.main.async {
             let data:[AnyHashable : Any] = notification.userInfo!
             if data["member"] as? String == User.getMyPin()! {
-                self.refresh()
+                self.reloadAllData()
             } else if data["state"] as? Int == 99 {
-                self.refresh()
+                self.reloadAllData()
             }
         }
     }
     
     @objc func onReceiveMessage(notification: NSNotification) {
-        DispatchQueue.main.async {
-            self.refresh()
-        }
+        reloadAllData()
     }
     
     @objc func onStatusChat(notification: NSNotification) {
-        DispatchQueue.main.async {
-            self.refresh()
+        reloadAllData()
+    }
+    
+    private func reloadAllData() {
+//        print("reloadAllData")
+        DispatchQueue.main.async { [weak self] in
+            if self?.timerReloadData == nil && !self!.isGettingData {
+                self?.refresh()
+            } else {
+                self?.timerReloadData?.invalidate()
+                self?.timerReloadData = nil
+                self?.timerReloadData = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false) { [weak self] _ in
+                    if self != nil && !self!.isGettingData {
+                        self?.refresh()
+                        self?.timerReloadData = nil
+                    }
+                }
+            }
         }
     }
     
@@ -1083,7 +1092,7 @@ public class ChatWALikeVC: UIViewController, UITableViewDataSource, UITableViewD
                         stringMessage.append(("🚫 _"+"You were deleted this message".localized()+"_").richText())
                     } else {
                         let imageStatus = NSTextAttachment()
-                        if data.messageScope != MessageScope.CALL && data.messageScope != MessageScope.MISSED_CALL {
+                        if data.messageScope != MessageScope.CALL && data.messageScope != MessageScope.MISSED_CALL && data.messageScope != MessageScope.GPT_CHATBOT {
                             let status = getRealStatus(messageId: data.messageId)
                             if status == "0" {
                                 imageStatus.image = UIImage(systemName: "xmark.circle")!.withTintColor(UIColor.red, renderingMode: .alwaysOriginal)
@@ -1117,6 +1126,9 @@ public class ChatWALikeVC: UIViewController, UITableViewDataSource, UITableViewD
                         }
                         stringMessage.append(NSAttributedString(string: fullname + ": ", attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 12 + String.offset(), weight: .medium)]))
                     }
+                    if data.messageScope == MessageScope.WHISPER && data.isBot == 1 {
+                        stringMessage.append(NSAttributedString(string: Utils.getGPTBotName() + ": ", attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 12 + String.offset(), weight: .medium)]))
+                    }
                     if data.lock == "1" {
                         stringMessage.append(("🚫 _"+"This message was deleted".localized()+"_").richText())
                     } else {

+ 30 - 3
NexilisLite/NexilisLite/Source/View/Chat/EditorGroup.swift

@@ -639,6 +639,9 @@ public class EditorGroup: UIViewController, CLLocationManagerDelegate {
                 data["name"] = c.string(forColumnIndex: 0)!
                 data["image_id"] = ""
                 c.close()
+            } else if f_pin == "-997" {
+                data["name"] = Utils.getGPTBotName()
+                data["image_id"] = ""
             } else {
                 data["name"] = "Unknown".localized()
             }
@@ -3182,9 +3185,9 @@ extension EditorGroup: UITextViewDelegate, CustomTextViewPasteDelegate {
                             }
                         }
                     }
-                    if "GPT SmartBot".lowercased().contains(text.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()) || text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
+                    if Utils.getGPTBotName().lowercased().contains(text.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()) || text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
                         let gptUser = User(pin: "-997",
-                                        firstName: "GPT SmartBot",
+                                        firstName: Utils.getGPTBotName(),
                                         lastName: "",
                                         thumb: "",
                                         userType: "0",
@@ -4259,7 +4262,7 @@ extension EditorGroup: UIContextMenuInteractionDelegate {
                             cursor.close()
                         } else if pinRes == "-997" {
                             let gptUser = User(pin: "-997",
-                                            firstName: "GPT SmartBot",
+                                            firstName: Utils.getGPTBotName(),
                                             lastName: "",
                                             thumb: "",
                                             userType: "0",
@@ -5593,6 +5596,27 @@ extension EditorGroup: UITableViewDelegate, UITableViewDataSource, AVAudioPlayer
                 }
                 profileMessage.contentMode = .scaleAspectFill
             }
+            else if dataMessages[indexPath.row]["f_pin"] as? String == "-997" {
+                if let urlGif = Bundle.resourceBundle(for: Nexilis.self).url(forResource: "pb_gpt_bot", withExtension: "gif") {
+                    profileMessage.sd_setImage(with: urlGif) { (image, error, cacheType, imageURL) in
+                        if error == nil {
+                            profileMessage.animationImages = image?.images
+                            profileMessage.animationDuration = image?.duration ?? 0.0
+                            profileMessage.animationRepeatCount = 0
+                            profileMessage.startAnimating()
+                        }
+                    }
+                } else if let urlGif = Bundle.resourcesMediaBundle(for: Nexilis.self).url(forResource: "pb_gpt_bot", withExtension: "gif") {
+                    profileMessage.sd_setImage(with: urlGif) { (image, error, cacheType, imageURL) in
+                        if error == nil {
+                            profileMessage.animationImages = image?.images
+                            profileMessage.animationDuration = image?.duration ?? 0.0
+                            profileMessage.animationRepeatCount = 0
+                            profileMessage.startAnimating()
+                        }
+                    }
+                }
+            }
             else if (pictureImage != "" && pictureImage != nil) {
                 profileMessage.setImage(name: pictureImage!)
                 profileMessage.contentMode = .scaleAspectFill
@@ -5659,6 +5683,9 @@ extension EditorGroup: UITableViewDelegate, UITableViewDataSource, AVAudioPlayer
             if dataMessages[indexPath.row]["f_pin"] as? String == "-999" {
                 nameSender.text = "Bot"
             }
+            else if dataMessages[indexPath.row]["f_pin"] as? String == "-997" {
+                nameSender.text = Utils.getGPTBotName()
+            }
             else {
                 nameSender.text = dataProfile["name"]
             }

+ 4 - 4
NexilisLite/NexilisLite/Source/View/Chat/EditorPersonal.swift

@@ -4579,9 +4579,9 @@ extension EditorPersonal: UITextViewDelegate, CustomTextViewPasteDelegate {
         listMentionWithText.removeAll()
         Database.shared.database?.inTransaction({ fmdb, rollback in
             do {
-                if "GPT SmartBot".lowercased().contains(text.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()) || text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
+                if Utils.getGPTBotName().lowercased().contains(text.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()) || text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
                     let gptUser = User(pin: "-997",
-                                    firstName: "GPT SmartBot",
+                                    firstName: Utils.getGPTBotName(),
                                     lastName: "",
                                     thumb: "",
                                     userType: "0",
@@ -5612,7 +5612,7 @@ extension EditorPersonal: UIContextMenuInteractionDelegate {
                             cursor.close()
                         } else if pinRes == "-997" {
                             let gptUser = User(pin: "-997",
-                                            firstName: "GPT SmartBot",
+                                            firstName: Utils.getGPTBotName(),
                                             lastName: "",
                                             thumb: "",
                                             userType: "0",
@@ -7055,7 +7055,7 @@ extension EditorPersonal: UITableViewDelegate, UITableViewDataSource, AVAudioPla
                         }
                     }
                 }
-                nameSender.text = "GPT SmartBot"
+                nameSender.text = Utils.getGPTBotName()
             } else {
                 let user = User.getData(pin: dataMessages[indexPath.row]["f_pin"] as? String)
                 getImage(name: user?.thumb ?? "", placeholderImage: UIImage(systemName: "person.circle.fill")!, tableView: tableView, indexPath: indexPath) { result, isDownloaded, image in

+ 2 - 2
NexilisLite/NexilisLite/Source/View/Control/ChangeDeviceViewController.swift

@@ -255,7 +255,7 @@ public class ChangeDeviceViewController: UIViewController {
                             if let publicKey = KeyManagerNexilis.getRSAX509PublicKeyBase64(privateKey: privateKey) {
                                 pk = publicKey
                             }
-                            let otp = try TOTPGenerator.generateTOTP(base32Secret: TOTPGenerator.getTOTP(), digits: 6, timeStepSeconds: 30)
+                            let otp = try TOTPGenerator.generateTOTP(base32Secret: TOTPGenerator.getTOTP(), digits: 6, timeStepSeconds: 300)
                             if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getSendVerifyChangeDevice(p_email: "", p_vercode: method == 0 ? "" : code, number: number, deviceFingerprint: df, publicKey: pk, signature: sign, totp: otp), timeout: 30 * 1000) {
                                 if !response.isOk() {
                                     if method == 1 {
@@ -383,7 +383,7 @@ public class ChangeDeviceViewController: UIViewController {
                             if let publicKey = KeyManagerNexilis.getRSAX509PublicKeyBase64(privateKey: privateKey) {
                                 pk = publicKey
                             }
-                            let otp = try TOTPGenerator.generateTOTP(base32Secret: TOTPGenerator.getTOTP(), digits: 6, timeStepSeconds: 30)
+                            let otp = try TOTPGenerator.generateTOTP(base32Secret: TOTPGenerator.getTOTP(), digits: 6, timeStepSeconds: 300)
                             if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getSendVerifyChangeDevice(p_email: email, p_vercode: code, deviceFingerprint: df, publicKey: pk, signature: sign, totp: otp), timeout: 30 * 1000) {
                                 if !response.isOk() {
                                     DispatchQueue.main.async {

+ 3 - 3
NexilisLite/NexilisLite/Source/View/Control/ContactChatViewController.swift

@@ -540,7 +540,7 @@ class ContactChatViewController: UITableViewController {
                 do {
                     if self.isChooser == nil {
                         let gptUser = User(pin: "-997",
-                                        firstName: "GPT SmartBot",
+                                        firstName: Utils.getGPTBotName(),
                                         lastName: "",
                                         thumb: "",
                                         userType: "0",
@@ -1590,7 +1590,7 @@ extension ContactChatViewController {
                                 stringMessage.append(("🚫 _"+"You were deleted this message".localized()+"_").richText())
                             } else {
                                 let imageStatus = NSTextAttachment()
-                                if data.messageScope != MessageScope.CALL && data.messageScope != MessageScope.MISSED_CALL && !data.messageId.contains("NTFPIN_") {
+                                if data.messageScope != MessageScope.CALL && data.messageScope != MessageScope.MISSED_CALL && !data.messageId.contains("NTFPIN_") && data.messageScope != MessageScope.GPT_CHATBOT {
                                     let status = getRealStatus(messageId: data.messageId)
                                     if status == "0" {
                                         imageStatus.image = UIImage(systemName: "xmark.circle")!.withTintColor(UIColor.red, renderingMode: .alwaysOriginal)
@@ -1625,7 +1625,7 @@ extension ContactChatViewController {
                                 stringMessage.append(NSAttributedString(string: fullname + ": ", attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 12 + String.offset(), weight: .medium)]))
                             }
                             if data.messageScope == MessageScope.WHISPER && data.isBot == 1 {
-                                stringMessage.append(NSAttributedString(string: "GPT SmartBot" + ": ", attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 12 + String.offset(), weight: .medium)]))
+                                stringMessage.append(NSAttributedString(string: Utils.getGPTBotName() + ": ", attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 12 + String.offset(), weight: .medium)]))
                             }
                             if data.lock == "1" {
                                 stringMessage.append(("🚫 _"+"This message was deleted".localized()+"_").richText())

+ 1 - 1
NexilisLite/NexilisLite/Source/View/Control/MFAViewController.swift

@@ -350,7 +350,7 @@ class MFAViewController: UIViewController {
                             }
                         }
 //                        let secret = "JBSWY3DPEHPK3PXP" // Google Authenticator example
-                        let otp = try TOTPGenerator.generateTOTP(base32Secret: TOTPGenerator.getTOTP(), digits: 6, timeStepSeconds: 30)
+                        let otp = try TOTPGenerator.generateTOTP(base32Secret: TOTPGenerator.getTOTP(), digits: 6, timeStepSeconds: 300)
                         tMessage.mBodies[CoreMessage_TMessageKey.TOTP] = otp
                         if let response = Nexilis.writeAndWait(message: tMessage) {
                             if response.isOk() {

+ 6 - 6
NexilisLite/NexilisLite/Source/View/Control/SettingTableViewController.swift

@@ -720,12 +720,12 @@ public class SettingTableViewController: UITableViewController, UIGestureRecogni
                                 Utils.setLastTabSelected(value: 0)
                                 Utils.setIsWATheme(value: false)
                                 UIApplication.shared.setAlternateIconName(nil)
-                                Database.shared.database?.inTransaction({ fmdb, rollback in
-                                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "GROUPZ", _where: "")
-                                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "GROUPZ_MEMBER", _where: "")
-                                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "DISCUSSION_FORUM", _where: "")
-                                    _ = Nexilis.write(message: CoreMessage_TMessageBank.getPostRegistration(p_pin: User.getMyPin() ?? ""))
-                                })
+//                                Database.shared.database?.inTransaction({ fmdb, rollback in
+//                                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "GROUPZ", _where: "")
+//                                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "GROUPZ_MEMBER", _where: "")
+//                                    _ = Database.shared.deleteRecord(fmdb: fmdb, table: "DISCUSSION_FORUM", _where: "")
+//                                    _ = Nexilis.write(message: CoreMessage_TMessageBank.getPostRegistration(p_pin: User.getMyPin() ?? ""))
+//                                })
                                 Nexilis.hideLoader {
                                     let alert = LibAlertController(title: "Successfully changed".localized(), message: "Please open the app again to see the changes".localized(), preferredStyle: .alert)
                                     alert.addAction(UIAlertAction(title: "OK".localized(), style: .default, handler: {(_) in

+ 3 - 3
NexilisLite/NexilisLite/Source/View/Control/SignUpSignIn.swift

@@ -254,7 +254,7 @@ public class SignUpSignIn: UIViewController {
                             if let publicKey = KeyManagerNexilis.getRSAX509PublicKeyBase64(privateKey: privateKey) {
                                 pk = publicKey
                             }
-                            let otp = try TOTPGenerator.generateTOTP(base32Secret: TOTPGenerator.getTOTP(), digits: 6, timeStepSeconds: 30)
+                            let otp = try TOTPGenerator.generateTOTP(base32Secret: TOTPGenerator.getTOTP(), digits: 6, timeStepSeconds: 300)
                             if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getSendVerifyChangeDevice(p_email: "", p_vercode: method == 0 ? "" : code, number: number, deviceFingerprint: df, publicKey: pk, signature: sign, totp: otp), timeout: 30 * 1000) {
                                 if !response.isOk() {
                                     if method == 1 {
@@ -382,7 +382,7 @@ public class SignUpSignIn: UIViewController {
                             if let publicKey = KeyManagerNexilis.getRSAX509PublicKeyBase64(privateKey: privateKey) {
                                 pk = publicKey
                             }
-                            let otp = try TOTPGenerator.generateTOTP(base32Secret: TOTPGenerator.getTOTP(), digits: 6, timeStepSeconds: 30)
+                            let otp = try TOTPGenerator.generateTOTP(base32Secret: TOTPGenerator.getTOTP(), digits: 6, timeStepSeconds: 300)
                             if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getSendVerifyChangeDevice(p_email: email, p_vercode: code, deviceFingerprint: df, publicKey: pk, signature: sign, totp: otp), timeout: 30 * 1000) {
                                 if !response.isOk() {
                                     DispatchQueue.main.async {
@@ -573,7 +573,7 @@ public class SignUpSignIn: UIViewController {
                         if let publicKey = KeyManagerNexilis.getRSAX509PublicKeyBase64(privateKey: privateKey) {
                             pk = publicKey
                         }
-                        let otp = try TOTPGenerator.generateTOTP(base32Secret: TOTPGenerator.getTOTP(), digits: 6, timeStepSeconds: 30)
+                        let otp = try TOTPGenerator.generateTOTP(base32Secret: TOTPGenerator.getTOTP(), digits: 6, timeStepSeconds: 300)
                         if let response = Nexilis.writeSync(message: CoreMessage_TMessageBank.getSignUpSignInAPI(p_name: name, p_password: md5Hex, deviceFingerprint: df, publicKey: pk, signature: sign, totp: otp), timeout: 30 * 1000) {
                             if response.getBody(key: CoreMessage_TMessageKey.ERRCOD, default_value: "99") == "20" {
                                 DispatchQueue.main.async {