runChatGptOAuthCliFlow function

Future<ChatGptOAuthCredentials?> runChatGptOAuthCliFlow({
  1. required void onStatus(
    1. String
    ),
  2. Future<bool> openBrowserFn(
    1. String
    ) = openBrowser,
  3. Future<ChatGptOAuthCredentials> exchangeFn({
    1. required String code,
    2. required String redirectUri,
    3. required String verifier,
    }) = _defaultExchange,
  4. Duration timeout = const Duration(minutes: 5),
})

Implementation

Future<ChatGptOAuthCredentials?> runChatGptOAuthCliFlow({
  required void Function(String) onStatus,
  Future<bool> Function(String) openBrowserFn = openBrowser,
  Future<ChatGptOAuthCredentials> Function({
        required String code,
        required String redirectUri,
        required String verifier,
      })
      exchangeFn =
      _defaultExchange,
  Duration timeout = const Duration(minutes: 5),
}) async {
  final server = ChatGptOAuthLocalCallbackServer();
  final verifier = generateChatGptPkceVerifier();
  final state = generateChatGptState();
  final redirectUri = await server.start(timeout: timeout);
  final authUrl = buildChatGptAuthorizeUrl(
    redirectUri: redirectUri,
    codeChallenge: generateChatGptPkceChallenge(verifier),
    state: state,
  );
  onStatus('listening for ChatGPT OAuth callback on $redirectUri');
  if (await openBrowserFn(authUrl.toString())) {
    onStatus('browser opened; complete authorization with ChatGPT');
  } else {
    onStatus('could not open browser automatically');
    onStatus('open this URL manually: $authUrl');
  }
  final callback = await server.waitForCallback();
  if (callback == null) {
    onStatus('no authorization callback received (timeout or cancelled)');
    return null;
  }
  if (callback.error != null) {
    onStatus(
      'ChatGPT authorization failed: ${callback.errorDescription ?? callback.error}',
    );
    return null;
  }
  if (callback.state != state ||
      callback.code == null ||
      callback.code!.isEmpty) {
    onStatus('ChatGPT authorization callback was invalid');
    return null;
  }
  try {
    final credentials = await exchangeFn(
      code: callback.code!,
      redirectUri: redirectUri,
      verifier: verifier,
    );
    onStatus('ChatGPT authorized');
    return credentials;
  } on Object catch (error) {
    onStatus('ChatGPT authorization failed: $error');
    return null;
  }
}