flutter_chatgpt_api
flutter_chatgpt_api copied to clipboard
Throwing exception
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Exception: ChatGPT failed to refresh auth token: Exception: Failed to refresh access token
#0 ChatGPTApi._refreshAccessToken (package:flutter_chatgpt_api/flutter_chatgpt_api.dart:152:7)
https://github.com/coskuncay/flutter_chatgpt_api/issues/1 ChatGPTApi.sendMessage (package:flutter_chatgpt_api/flutter_chatgpt_api.dart:50:25)
https://github.com/coskuncay/flutter_chatgpt_api/issues/2 _ChatScreenState._buildSubmit. (package:neural_ai/screens/chat.screen.dart:110:30)
I just found this package and now I came across this same issue, it happens because there is a little mistake in the flutter_chatgpt_api.dart file (the defaultUserAgent variable is used instead of the user agent the user specified).
To fix it replace the contents of that file with the following code:
library flutter_chatgpt_api;
import 'dart:convert';
import 'dart:io';
import 'package:flutter_chatgpt_api/src/models/models.dart';
import 'package:flutter_chatgpt_api/src/utils/utils.dart';
import 'package:http/http.dart' as http;
import 'package:uuid/uuid.dart';
part 'src/models/chat_message.model.dart';
class ChatGPTApi {
String sessionToken;
String clearanceToken;
String? apiBaseUrl;
String backendApiBaseUrl;
String userAgent;
final ExpiryMap<String, String> _accessTokenCache =
ExpiryMap<String, String>();
ChatGPTApi({
required this.sessionToken,
required this.clearanceToken,
this.apiBaseUrl = 'https://chat.openai.com/api',
this.backendApiBaseUrl = 'https://chat.openai.com/backend-api',
required this.userAgent,
});
Future<ChatResponse> sendMessage(
String message, {
String? conversationId,
String? parentMessageId,
}) async {
final accessToken = await _refreshAccessToken();
parentMessageId ??= const Uuid().v4();
final body = ConversationBody(
action: 'next',
conversationId: conversationId,
messages: [
Prompt(
content: PromptContent(contentType: 'text', parts: [message]),
id: const Uuid().v4(),
role: 'user',
)
],
model: 'text-davinci-002-render',
parentMessageId: parentMessageId,
);
final url = '$backendApiBaseUrl/conversation';
final response = await http.post(
Uri.parse(url),
headers: {
'user-agent': this.userAgent,
'x-openai-assistant-app-id': '',
'accept-language': 'en-US,en;q=0.9',
HttpHeaders.accessControlAllowOriginHeader: 'https://chat.openai.com',
HttpHeaders.refererHeader: 'https://chat.openai.com/chat',
'sec-ch-ua':
'"Not?A_Brand";v="8", "Chromium";v="108", "Google Chrome";v="108"',
'sec-ch-ua-platform': '"Windows"',
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'same-origin',
'Authorization': 'Bearer $accessToken',
'Content-Type': 'application/json',
'Accept': 'text/event-stream',
'Cookie': 'cf_clearance=$clearanceToken'
},
body: body.toJson(),
);
if (response.statusCode != 200) {
if (response.statusCode == 429) {
throw Exception('Rate limited');
} else {
throw Exception('Failed to send message');
}
} else if (_errorMessages.contains(response.body)) {
throw Exception('OpenAI returned an error');
}
String longestLine =
response.body.split('\n').reduce((a, b) => a.length > b.length ? a : b);
var result = longestLine.replaceFirst('data: ', '');
var messageResult = ConversationResponseEvent.fromJson(result);
var lastResult = messageResult.message?.content.parts.first;
if (lastResult == null) {
throw Exception('No response from OpenAI');
} else {
return ChatResponse(
message: lastResult,
messageId: messageResult.message!.id,
conversationId: messageResult.conversationId,
);
}
}
Future<String> _refreshAccessToken() async {
Map<String, String> defaultHeaders = {
'user-agent': this.userAgent,
'x-openai-assistant-app-id': '',
'accept-language': 'en-US,en;q=0.9',
HttpHeaders.accessControlAllowOriginHeader: 'https://chat.openai.com',
HttpHeaders.refererHeader: 'https://chat.openai.com/chat',
'sec-ch-ua':
'"Not?A_Brand";v="8", "Chromium";v="108", "Google Chrome";v="108"',
'sec-ch-ua-platform': '"Windows"',
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'same-origin',
};
final cachedAccessToken = _accessTokenCache['KEY_ACCESS_TOKEN'];
if (cachedAccessToken != null) {
return cachedAccessToken;
}
try {
final res = await http.get(
Uri.parse('$apiBaseUrl/auth/session'),
headers: {
'cookie':
'cf_clearance=$clearanceToken;__Secure-next-auth.session-token=$sessionToken',
'accept': '*/*',
...defaultHeaders,
},
);
if (res.statusCode != 200) {
throw Exception('Failed to refresh access token, ${res.statusCode}');
}
final accessToken = jsonDecode(res.body)['accessToken'];
if (accessToken == null) {
throw Exception(
'Failed to refresh access token, token in response is null');
}
_accessTokenCache['KEY_ACCESS_TOKEN'] = accessToken;
return accessToken;
} catch (err) {
throw Exception('ChatGPT failed to refresh auth token: $err');
}
}
}
const _errorMessages = [
"{\"detail\":\"Hmm...something seems to have gone wrong. Maybe try me again in a little bit.\"}",
];
Don't forget that instead of using the package from pub.dev you should download the code and place it in the packages folder (in Linux is /home/youruser/snap/flutter/common/flutter/.pub-cache/hosted/pub.dartlang.org/ if you installed flutter with snap, if not don't worry the route is very similar, look it up online), edit the file I told you, add the dependency to your pubspec.yaml
file and run flutter pub get
. If you use the version from pub.dev and then edit the file, I think when you run flutter pub get
the content of the files get replaced to the original. This shouldn't be necessary once @coskuncay fixes it in the master branch.
Then in your code initialize the api like this:
_api = ChatGPTApi(
sessionToken: SESSION_TOKEN,
clearanceToken: CLEARANCE_TOKEN,
userAgent:
'YOUR USER AGENT',
);
The user agent must match with the one used in the session from where the sessionToken and clearanceToken where extracted. You can find your user agent with Dev Tools in the request headers.
same issue
Hi @itsalfredakku @csc7545 @Gabriel11101 , first of all, thank you for using the package, I haven't had time to solve the problem due to my busy schedule. I will fix it asap. pull requests are welcome :)