From 457aa8ee49b70e31cff143fd1f719461f4b2d6b3 Mon Sep 17 00:00:00 2001 From: iHTCboy Date: Tue, 13 Dec 2022 11:26:58 +0800 Subject: [PATCH] =?UTF-8?q?fix=EF=BC=9ACloudflare=20cookie=20support?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iChatGPT.xcodeproj/project.pbxproj | 8 +-- iChatGPT/ChatInputView.swift | 2 +- iChatGPT/Models/AIChatModel.swift | 6 ++- iChatGPT/Models/ChatGPT.swift | 21 +++++--- iChatGPT/TokenSettingView.swift | 87 +++++++++++++++++++++++------- 5 files changed, 92 insertions(+), 32 deletions(-) diff --git a/iChatGPT.xcodeproj/project.pbxproj b/iChatGPT.xcodeproj/project.pbxproj index 4a69581..8b41bd2 100644 --- a/iChatGPT.xcodeproj/project.pbxproj +++ b/iChatGPT.xcodeproj/project.pbxproj @@ -492,7 +492,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 2022.12.10; + CURRENT_PROJECT_VERSION = 2022.12.13; DEVELOPMENT_ASSET_PATHS = "\"iChatGPT/Preview Content\""; DEVELOPMENT_TEAM = ""; ENABLE_PREVIEWS = YES; @@ -510,7 +510,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.1.0; + MARKETING_VERSION = 1.1.1; PRODUCT_BUNDLE_IDENTIFIER = com.37iOS.iChatGPT; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -532,7 +532,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 2022.12.10; + CURRENT_PROJECT_VERSION = 2022.12.13; DEVELOPMENT_ASSET_PATHS = "\"iChatGPT/Preview Content\""; DEVELOPMENT_TEAM = ""; ENABLE_PREVIEWS = YES; @@ -550,7 +550,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.1.0; + MARKETING_VERSION = 1.1.1; PRODUCT_BUNDLE_IDENTIFIER = com.37iOS.iChatGPT; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/iChatGPT/ChatInputView.swift b/iChatGPT/ChatInputView.swift index 5670044..b71d7b9 100644 --- a/iChatGPT/ChatInputView.swift +++ b/iChatGPT/ChatInputView.swift @@ -44,7 +44,7 @@ struct ChatInputView: View { .padding(.trailing, 8) if #available(iOS 15.0, *) { - serachBar.submitLabel(.search) + serachBar.submitLabel(.send) } else { serachBar } diff --git a/iChatGPT/Models/AIChatModel.swift b/iChatGPT/Models/AIChatModel.swift index a0e853a..1532f96 100644 --- a/iChatGPT/Models/AIChatModel.swift +++ b/iChatGPT/Models/AIChatModel.swift @@ -8,6 +8,8 @@ import Foundation +let ChatGPTUserAgentKey = "ChatGPTUserAgentKey" +let ChatGPTCfClearanceKey = "ChatGPTCfClearanceKey" let ChatGPTSessionTokenKey = "ChatGPTSessionTokenKey" // MARK: - Welcome1 @@ -54,7 +56,9 @@ class AIChatModel: ObservableObject { func reloadChatbot() { isRefreshSession = false + let userAgent = UserDefaults.standard.string(forKey: ChatGPTUserAgentKey) ?? "" + let cfClearance = UserDefaults.standard.string(forKey: ChatGPTCfClearanceKey) ?? "" let chatGPTSessionToken = UserDefaults.standard.string(forKey: ChatGPTSessionTokenKey) ?? "" - bot = Chatbot(sessionToken: chatGPTSessionToken) + bot = Chatbot(sessionToken: chatGPTSessionToken, cfClearance: cfClearance, userAgent: userAgent) } } diff --git a/iChatGPT/Models/ChatGPT.swift b/iChatGPT/Models/ChatGPT.swift index a88554d..3dbffea 100644 --- a/iChatGPT/Models/ChatGPT.swift +++ b/iChatGPT/Models/ChatGPT.swift @@ -13,20 +13,25 @@ import Combine class Chatbot { let apUrl = "https://chat.openai.com/" + let cfClearanceKey = "cf_clearance" let sessionTokenKey = "__Secure-next-auth.session-token" let timeout = 20 /// Code=-1001 "The request timed out." /// Code=-1017 "cannot parse response" /// Code=-1009 "The Internet connection appears to be offline." let errorCodes = [-1001, -1017, -1009] - var sessionToken: String + var sessionToken: String + var cfClearance: String + var userAgent: String? var authorization = "" var conversationId = "" var parentId = "" var userAvatarUrl = "" - init(sessionToken: String) { + init(sessionToken: String, cfClearance: String, userAgent: String?) { self.sessionToken = sessionToken + self.cfClearance = cfClearance + self.userAgent = userAgent Task { await refreshSession() } @@ -36,9 +41,10 @@ class Chatbot { return [ "Host": "chat.openai.com", "Accept": "text/event-stream", - "Authorization": "Bearer \(self.authorization)", + "Authorization": "Bearer \(self.authorization)", + "Cookie": "\(cfClearanceKey)=\(self.cfClearance)", "Content-Type": "application/json", - "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.1 Safari/605.1.15", + "User-Agent": self.userAgent ?? "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.1 Safari/605.1.15", "X-Openai-Assistant-App-Id": "", "Connection": "keep-alive", "Accept-Language": "zh-CN,zh-Hans;en-US,en;q=0.9", @@ -70,13 +76,14 @@ class Chatbot { } func refreshSession(retry: Int = 1) async { - let cookies = "\(sessionTokenKey)=\(self.sessionToken)" + let cookies = "\(cfClearanceKey)=\(self.cfClearance); \(sessionTokenKey)=\(self.sessionToken)" let url = self.apUrl + "api/auth/session" let userAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.1 Safari/605.1.15" var request = URLRequest(url: URL(string: url)!) request.httpMethod = "GET" - request.addValue(userAgent, forHTTPHeaderField: "User-Agent") + request.addValue(self.userAgent ?? userAgent, forHTTPHeaderField: "User-Agent") request.addValue(cookies, forHTTPHeaderField: "Cookie") + request.httpShouldHandleCookies = true do { let (data, response) = try await URLSession.shared.data(for: request) let json = try JSONSerialization.jsonObject(with: data, options: []) @@ -117,7 +124,7 @@ class Chatbot { let url = self.apUrl + "backend-api/conversation" var request = URLRequest(url: URL(string: url)!) request.httpMethod = "POST" - request.allHTTPHeaderFields = headers() + request.allHTTPHeaderFields = headers() let dict = getPayload(prompt: prompt) do { let jsonData = try JSONSerialization.data(withJSONObject: dict, options: []) diff --git a/iChatGPT/TokenSettingView.swift b/iChatGPT/TokenSettingView.swift index 54b2ed1..527b9fd 100644 --- a/iChatGPT/TokenSettingView.swift +++ b/iChatGPT/TokenSettingView.swift @@ -12,8 +12,12 @@ struct TokenSettingView: View { @Binding var isAddPresented: Bool @StateObject var chatModel: AIChatModel - @State private var text: String = "" - @State private var error: String = "" + @State private var sessionToken: String = "" + @State private var cfClearance: String = "" + @State private var userAgent: String = "" + @State private var sError: String = "" + @State private var cError: String = "" + @State private var uError: String = "" private let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String private let appSubVersion = Bundle.main.infoDictionary?["CFBundleVersion"] as? String @@ -39,32 +43,77 @@ struct TokenSettingView: View { VStack(alignment: .leading) { Text("Session Token:") - MultilineTextField("请输入 Session Token", text: $text, maxHeight: 300, onCommit: { - #if DEBUG - print("Final text: \(text)") - #endif - }) - .overlay(RoundedRectangle(cornerRadius: 5) - .stroke(Color.secondary)) + let sTextField = TextField(" 请输入 session_token", text: $sessionToken) + .frame(height: 40) + .overlay(RoundedRectangle(cornerRadius: 5) + .stroke(Color(.tertiaryLabel))) - if error.count > 0 && text.count == 0 { - Text(error) + if #available(iOS 15.0, *) { + sTextField.submitLabel(.done) + } + + if sError.count > 0 && sessionToken.isEmpty { + Text(sError) + .foregroundColor(.red) + } + + Text("Cf Clearance:") + .padding(.top, 15) + let cTextField = TextField(" 请输入 cf_clearance", text: $cfClearance) + .frame(height: 40) + .overlay(RoundedRectangle(cornerRadius: 5) + .stroke(Color.secondary)) + + if #available(iOS 15.0, *) { + cTextField.submitLabel(.done) + } + + if cError.count > 0 && cfClearance.isEmpty { + Text(cError) + .foregroundColor(.red) + } + + Text("User Agent:") + .padding(.top, 15) + let uTextField = TextField(" 请输入 user_agent", text: $userAgent) + .frame(height: 40) + .overlay(RoundedRectangle(cornerRadius: 5) + .stroke(Color.secondary)) + + if #available(iOS 15.0, *) { + uTextField.submitLabel(.done) + } + + if uError.count > 0 && userAgent.isEmpty { + Text(uError) .foregroundColor(.red) + .padding(.bottom, 10) } } .padding([.leading, .trailing], 20) Spacer() Button(action: { - if text.isEmpty { - error = "Session Token 不能为空!" - } else { - UserDefaults.standard.set(text, forKey: ChatGPTSessionTokenKey) - isAddPresented = false - chatModel.isRefreshSession = true + guard !sessionToken.isEmpty else { + sError = "Session Token 不能为空!" + return + } + guard !cfClearance.isEmpty else { + cError = "Cf Clearance 不能为空!" + return } + guard !userAgent.isEmpty else { + uError = "User Agent 不能为空!" + return + } + + UserDefaults.standard.set(sessionToken, forKey: ChatGPTSessionTokenKey) + UserDefaults.standard.set(cfClearance, forKey: ChatGPTCfClearanceKey) + UserDefaults.standard.set(userAgent, forKey: ChatGPTUserAgentKey) + isAddPresented = false + chatModel.isRefreshSession = true }) { - Text("确认") + Text("保存") .font(.title3) .foregroundColor(.blue) .padding([.leading, .trailing], 20) @@ -83,7 +132,7 @@ struct TokenSettingView: View { .font(.footnote) .foregroundColor(.secondary) .multilineTextAlignment(.center) - .padding(.bottom, 5) + .padding(.bottom, 25) } } }