# Стартовые профили

Мы требуем от вас отправить отдельный запрос на запуск профиля. В основном по нескольким причинам:

  1. Чтобы заблокировать профиль, чтобы другие не могли использовать его, пока ваш сеанс активен.
  2. Чтобы запретить вам использовать профиль, если он используется кем-то другим или если он был удален, или если есть проблемы с некоторыми зависимостями, такими как прокси.

Если вы не хотите блокировать профиль или хотите использовать его, даже если он был заблокирован кем-то другим – это возможно, но вам все равно придется отправить этот запрос, только с другими параметрами.

# Что такое блокировка профиля

Каждому сеансу профиля (кроме тех, которые запускаются без блокировки) мы назначаем специальный ключ — profileLock. Это псевдо случайно сгенерированная строка UUID, например. 4729de92-e283-4834-9e70-1d5913c4cf4d.

Если сессия в данный момент активна, т.е. профиль был запущен и не остановлен, то загрузка папки и импорт файлов cookie разрешены только в том случае, если именно этот ключ указан в соответствующем запросе. Таким способом мы понимаем что человек, загружающий папку и файлы cookie, именно тот кто запускал профиль.

Проще говоря: если вы хотите использовать механизм блокировки, вам необходимо предоставить текущий profileLock для возможности загрузить папку профиля. И запуск профиля нужен для того, чтобы поставить эту блокировку.

# Запрос

Запрос — «POST https://api.surfinite.com/profiles/{profile_id}/start», и вы должны проверить его в Справочник по API. Здесь мы просто опишем параметры и ответы.

Таким образом, помимо api_key, у вас есть возможность установить два параметра URL: use_lock и current_lock.

  1. Первый, use_lock (по умолчанию true), указывает, хотите ли вы заблокировать профиль. (и получить ошибку, если профиль уже заблокирован). Если запрос будет успешным, вы получите ответ JSON, содержащий ProfileLock и BrowserKey для вашего сеанса.
  2. Второй параметр, current_lock, является необязательным. Если профиль в настоящее время используется кем то другим, вы можете фактически переопределить его сеанс, предоставив его «profileLock». Вы можете переопределить любой сеанс как владелец ключа API, но об этом позже.

Ответ об успехе (200) представляет собой объект JSON:

{ 
  "browserKey": "key_to_start_browser", 
  "profileLock": "lock_of_current_session" 
}

BrowserKey — это параметр, не допускающий значения NULL. Но profileLock будет отсутствовать, если вы установите use_lock=false.

Ответы на ошибки можно найти в Справочник по API.

# Browser Key

Browser Key — это еще один способ идентифицировать ваш сеанс. Дело в том, что ProfileLock может отсутствовать, поэтому мы бы не знали, кто запускает профиль. Но «browserKey» всегда будет там. Вам нужен только этот параметр для запуска браузера и он действителен в течение 60 минут после запуска профиля (так что вы можете закрыть и запустить браузер несколько раз в течение этого часа без необходимости отправки нового запроса на запуск).

# Пример кода

val apiUrl = "https://api.surfinite.com"

val profileId = "my_profile_id"
val apiKey = "MY_API_KEY"
val useLock = true

val url = "$apiUrl/profiles/$profileId/start?use_lock=$useLock&api_key=$apiKey"

val client = HttpClient(CIO) { expectSuccess = true }
val responseString = runCatching {
    client.post(url).bodyAsText()
}.getOrElse { it: Throwable ->
    when (it) {
        is ClientRequestException -> {
            when (it.response.status) {
                HttpStatusCode.Unauthorized -> println("Unauthorized: bad api key") // 401
                HttpStatusCode.NotFound -> println("Profile not found") // 404
                HttpStatusCode.Conflict -> { // 409
                    // Response body is a JSON object containing the profile lock,
                    // so you can resend the request with it and override current session
                    println("Profile is already being used")
                }
                HttpStatusCode.Gone -> { // 410
                    // The profile is in your Recycle Bin, you can still restore it
                    println("The profile was deleted")
                }
                HttpStatusCode.UnprocessableEntity -> println("Profile is synchronizing") // 422
                HttpStatusCode.Locked -> { // 423
                    // Response body is a JSON object containing the profile lock,
                    // so you can resend the request with it and override current session
                    println("Your current_lock parameter was incorrect")
                }
                HttpStatusCode.FailedDependency -> { // 424
                    // Profile had a proxy assigned from the Proxy List, and it got deleted.
                    // Update the profile with a new proxy and then restart the profile
                    println("Assigned proxy does not exist")
                }
                else -> println("Server responded with: ${it.response.status}")
            }

            // Just print the body in case it contains a useful message
            println(it.response.bodyAsText())
        }
        is TimeoutException -> println("Request timed out")
        is ConnectException -> println("Server does not respond or you have no internet")
        else -> {
            // Unknown error
            it.printStackTrace()
        }
    }
    return
}

val responseJSON = Json.parseToJsonElement(responseString).jsonObject
val browserKey = responseJSON["browserKey"]!!.jsonPrimitive.content
val profileLock = responseJSON["profileLock"]!!.jsonPrimitive.content

println("Got the browserKey: $browserKey and profileLock: $profileLock")