checkLimitsAndMakeRequest function

Future<void> checkLimitsAndMakeRequest(
  1. {required String apiUserName,
  2. required String apiToken,
  3. required String link,
  4. required String userName,
  5. required PreJoinPageParameters parameters,
  6. bool validate = true}
)

checkLimitsAndMakeRequest

Checks for rate limits and establishes a socket connection if permissible.

Parameters:

  • apiUserName (String): The API username.
  • apiToken (String): The API token.
  • link (String): The link to connect.
  • userName (String): The user's display name.
  • parameters (PreJoinPageParameters): The parameters for callbacks and socket handling.
  • validate (bool): Whether to validate the primary socket connection.

Returns:

  • Future<void>: Completes when the request and connection are handled.

Implementation

Future<void> checkLimitsAndMakeRequest({
  required String apiUserName,
  required String apiToken,
  required String link,
  required String userName,
  required PreJoinPageParameters parameters,
  bool validate = true,
}) async {
  const int maxAttempts = 10;
  const int rateLimitDuration = 3 * 60 * 60 * 1000; // 3 hours in milliseconds
  const int timeoutDuration = 10000; // 10 seconds

  final prefs = await SharedPreferences.getInstance();
  int unsuccessfulAttempts = prefs.getInt('unsuccessfulAttempts') ?? 0;
  int lastRequestTimestamp = prefs.getInt('lastRequestTimestamp') ?? 0;

  if (unsuccessfulAttempts >= maxAttempts &&
      DateTime.now().millisecondsSinceEpoch - lastRequestTimestamp <
          rateLimitDuration) {
    parameters.showAlert!(
      message: "Too many unsuccessful attempts. Please try again later.",
      type: "danger",
      duration: 3000,
    );
    return;
  }

  try {
    parameters.updateIsLoadingModalVisible(true);

    // Attempt to connect the socket with a timeout
    final socketFuture = parameters.connectSocket(
      ConnectSocketOptions(
        apiUserName: apiUserName,
        apiKey: "", // Assuming API Key is not required if API Token is provided
        apiToken: apiToken,
        link: link,
      ),
    );

    final socket = await socketFuture.timeout(
      const Duration(milliseconds: timeoutDuration),
      onTimeout: () {
        throw TimeoutException("Socket connection timed out");
      },
    );

    if (socket.id!.isNotEmpty) {
      // Reset unsuccessful attempts on success
      prefs.setInt('unsuccessfulAttempts', 0);
      prefs.setInt(
          'lastRequestTimestamp', DateTime.now().millisecondsSinceEpoch);

      if (validate) {
        parameters.updateSocket(socket);
      } else {
        parameters.updateLocalSocket!(socket);
      }

      // Update other parameters
      parameters.updateApiUserName(apiUserName);
      parameters.updateApiToken(apiToken);
      parameters.updateLink(link);
      parameters.updateRoomName(apiUserName);
      parameters.updateMember(userName);

      if (validate) {
        parameters.updateValidated(true);
      }
    } else {
      // Increment unsuccessful attempts
      unsuccessfulAttempts += 1;
      prefs.setInt('unsuccessfulAttempts', unsuccessfulAttempts);
      parameters.updateIsLoadingModalVisible(false);
      parameters.showAlert!(
        message: "Invalid credentials.",
        type: "danger",
        duration: 3000,
      );
    }
  } on TimeoutException catch (_) {
    // Handle timeout
    unsuccessfulAttempts += 1;
    prefs.setInt('unsuccessfulAttempts', unsuccessfulAttempts);
    parameters.updateIsLoadingModalVisible(false);
    parameters.showAlert!(
      message: "Socket connection timed out. Please try again.",
      type: "danger",
      duration: 3000,
    );
  } catch (error) {
    // Handle other errors
    unsuccessfulAttempts += 1;
    prefs.setInt('unsuccessfulAttempts', unsuccessfulAttempts);
    parameters.updateIsLoadingModalVisible(false);
    parameters.showAlert!(
      message:
          "Unable to connect. Please check your credentials and try again.",
      type: "danger",
      duration: 3000,
    );
  } finally {
    parameters.updateIsLoadingModalVisible(false);
    prefs.setInt('lastRequestTimestamp', DateTime.now().millisecondsSinceEpoch);
  }
}