add_cap( $cap ); } $role = get_role( 'administrator' ); foreach ( $capabilities as $cap ) { $role->add_cap( $cap ); } $role = get_role( 'editor' ); foreach ( $capabilities as $cap ) { $role->add_cap( $cap ); } $role = get_role( 'author' ); foreach ( $capabilities as $cap ) { $role->add_cap( $cap ); } */ function reactpress_enqueue_scripts() { if (is_page('trips')) { wp_dequeue_script('currency-converter'); wp_dequeue_script('swup'); } } add_action('wp_enqueue_scripts', 'reactpress_enqueue_scripts', 20000); function reactpress_head() { global $wp_query; if (is_page('trips')) { ?> 'get_post_meta_for_api', 'schema' => null, ) ); } function get_post_meta_for_api( $obj ) { $postmeta = get_post_meta( $obj['id']); //=============== $apiKey = "0772153bce5238310c5a3fcbe783d1a7"; $cityId = get_field('city_code', $obj['id']); $apiUrl = "https://api.openweathermap.org/data/2.5/weather?id=" . $cityId . "&lang=ru&units=metric&APPID=" . $apiKey; $data = get_transient('weather_data_'.$cityId); if( empty($data) ){ $crequest = curl_init(); curl_setopt($crequest, CURLOPT_HEADER, 0); curl_setopt($crequest, CURLOPT_RETURNTRANSFER, 1); curl_setopt($crequest, CURLOPT_URL, $apiUrl); curl_setopt($crequest, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($crequest, CURLOPT_VERBOSE, 0); curl_setopt($crequest, CURLOPT_SSL_VERIFYPEER, false); $response = curl_exec($crequest); curl_close($crequest); $data = json_decode($response); set_transient('weather_data_'.$cityId, $data, 3600); // 3600 in seconds = 1h } $postmeta['weather'] = [ 'description' => ucwords($data->weather[0]->description), 'icon' => $data->weather[0]->icon, 'temp' => intval($data->main->temp) ]; //=============== foreach ($postmeta as $key => $field){ if ($key == 'cost_of_living_raw'){ $field = unserialize($field[0]); $postmeta[$key] = $field; } if ($key == 'country'){ $country = get_field_object('country', $obj['id']); $country = $country['choices'][$country['value']]; $postmeta[$key] = $country; } } return $postmeta; } //=================================================================================== //=== aviasales === $travelpayouts_token = '6d0c907fad90bb689a5db94d75b3789d'; // add_action('rest_api_init', function () { // register_rest_route( 'aviasales/v1', '/aviasales/', array( // 'methods' => 'GET', // 'callback' => 'aviasales', // )); // }); // function aviasales($request) { // global $travelpayouts_token; // $url = 'https://api.travelpayouts.com/aviasales/v3/prices_for_dates'; // //$request->get_param('cheap') // $params = [ // 'origin' => $request->get_param('departure_city'), // 'destination' => $request->get_param('destination_city'), // 'departure_at' => $request->get_param('departure_date'), // //'trip_class' => $request->get_param('type'), // 'unique' => 'false', // 'sorting' => 'price', // // 'direct' => 'false', // 'currency' => 'usd', // 'limit' => '15', //100 // 'page' => '1', // 'token' => $travelpayouts_token, // ]; // if ($request->get_param('direction') == 'oneway') { // $params['one_way'] = 'true'; // } else { // $params['one_way'] = 'false'; // $params['return_at'] = $request->get_param('return_date'); // } // //$request->get_param('persons') // $ch = curl_init($url.'?' . http_build_query($params)); // curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // curl_setopt($ch, CURLOPT_HEADER, false); // curl_setopt($ch, CURLOPT_ENCODING, "gzip, deflate"); // $result = curl_exec($ch); // $result = json_decode($result); // curl_close($ch); // //file_put_contents($_SERVER['DOCUMENT_ROOT'].'/data.txt', print_r($params, true), FILE_APPEND); // //file_put_contents($_SERVER['DOCUMENT_ROOT'].'/data.txt', print_r($result, true), FILE_APPEND); // return $result; // } add_action('rest_api_init', function () { register_rest_route('aviasales/v1', '/search/', array( 'methods' => 'GET', 'callback' => 'aviasales_search', )); }); function aviasales_search($request) { $log_file = $_SERVER['DOCUMENT_ROOT'] . '/flight_logs.txt'; $debug_log_file = $_SERVER['DOCUMENT_ROOT'] . '/debug_log_flights.txt'; function log_message($log_file, $message) { $timestamp = date("Y-m-d H:i:s"); file_put_contents($log_file, "[$timestamp] $message" . PHP_EOL, FILE_APPEND); } log_message($log_file, "Starting flight search request."); $marker = '402943'; $host = 'travcave.ru'; $user_ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown'; $locale = 'en'; $trip_class = 'Y'; $signature_token = '6d0c907fad90bb689a5db94d75b3789d'; $segments = [ [ 'origin' => $request->get_param('departure_city'), 'destination' => $request->get_param('destination_city'), 'date' => $request->get_param('departure_date') ] ]; if ($request->get_param('return_date')) { $segments[] = [ 'origin' => $request->get_param('return_city'), 'destination' => $request->get_param('return_destination_city'), 'date' => $request->get_param('return_date') ]; } $params = [ 'host' => $host, 'marker' => $marker, 'user_ip' => $user_ip, 'locale' => $locale, 'trip_class' => $trip_class, 'passengers' => [ 'adults' => (int) $request->get_param('adults'), 'children' => (int) $request->get_param('children'), 'infants' => (int) $request->get_param('infants') ], 'segments' => $segments ]; log_message($debug_log_file, "Received parameters: " . json_encode($params)); $signature_elements = [ $signature_token, $host, $locale, $marker, $params['passengers']['adults'], $params['passengers']['children'], $params['passengers']['infants'], $params['segments'][0]['date'], $params['segments'][0]['destination'], // Reverse order for signature $params['segments'][0]['origin'] // Reverse order for signature ]; if (isset($params['segments'][1])) { $signature_elements = array_merge($signature_elements, [ $params['segments'][1]['date'], $params['segments'][1]['destination'], // Reverse order for signature $params['segments'][1]['origin'] // Reverse order for signature ]); } $signature_elements = array_merge($signature_elements, [ $trip_class, $user_ip ]); $signature_string = implode(':', $signature_elements); $signature = md5($signature_string); $params['signature'] = $signature; $json_params = json_encode($params); if (json_last_error() !== JSON_ERROR_NONE) { $json_error = json_last_error_msg(); log_message($log_file, "JSON encode error: $json_error"); return array('error' => 'JSON encode error', 'message' => $json_error); } log_message($log_file, "Request parameters: $json_params"); $url = 'http://api.travelpayouts.com/v1/flight_search'; log_message($log_file, "Request URL: $url"); $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_HEADER, false); curl_setopt($ch, CURLOPT_ENCODING, "gzip, deflate"); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $json_params); curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json')); curl_setopt($ch, CURLOPT_VERBOSE, true); ob_start(); $result = curl_exec($ch); $curl_error = curl_error($ch); $verbose_log = ob_get_contents(); ob_end_clean(); log_message($log_file, "CURL error (if any): $curl_error"); log_message($log_file, "CURL verbose log: $verbose_log"); log_message($log_file, "API response: $result"); $response_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); log_message($log_file, "HTTP response code: $response_code"); curl_close($ch); if ($response_code != 200) { log_message($log_file, "API request failed with response code: $response_code"); return array('error' => 'API request failed', 'response_code' => $response_code); } $result = json_decode($result, true); if (json_last_error() !== JSON_ERROR_NONE) { $json_error = json_last_error_msg(); log_message($log_file, "JSON decode error: $json_error"); return array('error' => 'JSON decode error', 'message' => $json_error); } if (empty($result)) { log_message($log_file, "Empty result received from API."); return array('error' => 'No results', 'message' => 'No results returned from API.'); } log_message($log_file, "Returning result to client."); return $result; } add_action('rest_api_init', function () { register_rest_route('aviasalescity/v1', '/autocomplete/', array( 'methods' => 'GET', 'callback' => 'aviasales_city_autocomplete', )); }); function aviasales_city_autocomplete($request) { $log_file = $_SERVER['DOCUMENT_ROOT'] . '/flight_logs.txt'; $debug_log_file = $_SERVER['DOCUMENT_ROOT'] . '/debug_log_flights.txt'; // Helper function to log messages function log_message($log_file, $message) { $timestamp = date("Y-m-d H:i:s"); file_put_contents($log_file, "[$timestamp] $message" . PHP_EOL, FILE_APPEND); } log_message($log_file, "Starting city autocomplete request."); log_message($debug_log_file, "Starting city autocomplete request."); $url = 'https://autocomplete.travelpayouts.com/places2'; log_message($log_file, "Request URL: $url"); log_message($debug_log_file, "Request URL: $url"); $params = [ 'locale' => 'ru', 'term' => $request->get_param('city'), ]; log_message($log_file, "Request parameters: " . http_build_query($params)); log_message($debug_log_file, "Request parameters: " . http_build_query($params)); $ch = curl_init($url . '?' . http_build_query($params)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_HEADER, false); $result = curl_exec($ch); $curl_error = curl_error($ch); log_message($log_file, "CURL error (if any): $curl_error"); log_message($debug_log_file, "CURL error (if any): $curl_error"); log_message($log_file, "API response: $result"); log_message($debug_log_file, "API response: $result"); $result = json_decode($result, true); curl_close($ch); if (json_last_error() !== JSON_ERROR_NONE) { $json_error = json_last_error_msg(); log_message($log_file, "JSON decode error: $json_error"); log_message($debug_log_file, "JSON decode error: $json_error"); return array('error' => 'JSON decode error', 'message' => $json_error); } if (empty($result)) { log_message($log_file, "Empty result received from API."); log_message($debug_log_file, "Empty result received from API."); return array('error' => 'No results', 'message' => 'No results returned from API.'); } $result = array_slice($result, 0, 10); log_message($log_file, "Returning result to client."); log_message($debug_log_file, "Returning result to client."); return $result; } add_action('rest_api_init', function () { register_rest_route( 'aviasalescity/v1', '/aviasalescity/', array( 'methods' => 'GET', 'callback' => 'aviasalescity', )); }); function aviasalescity($request) { $url = 'https://autocomplete.travelpayouts.com/places2'; $params = [ 'locale' => 'ru', //'types[]' => 'airport',//, 'city' 'term' => $request->get_param('city'), ]; $ch = curl_init($url.'?' . http_build_query($params)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_HEADER, false); $result = curl_exec($ch); $result = json_decode($result); $result = array_slice($result, 0, 10); curl_close($ch); //file_put_contents($_SERVER['DOCUMENT_ROOT'].'/data.txt', print_r($result, true), FILE_APPEND); return $result; } //=================================================================================== //=== hotels === // add_action('rest_api_init', function () { // register_rest_route( 'hotels/v1', '/hotels/', array( // 'methods' => 'GET', // 'callback' => 'hotels', // )); // }); // function hotels($request) { // //return '1234'; // //file_put_contents($_SERVER['DOCUMENT_ROOT'].'/data.txt', print_r($params, true), FILE_APPEND); // $travelpayouts_token = '6d0c907fad90bb689a5db94d75b3789d'; // $url = 'https://engine.hotellook.com/api/v2/lookup.json'; // $params = [ // 'query' => $request->get_param('city'), // 'lang' => 'ru', // 'lookFor' => 'city', // 'limit' => 1, // 'token' => $travelpayouts_token, // ]; // $ch = curl_init($url.'?' . http_build_query($params)); // curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // curl_setopt($ch, CURLOPT_HEADER, false); // $result = curl_exec($ch); // $result = json_decode($result); // curl_close($ch); // //file_put_contents($_SERVER['DOCUMENT_ROOT'].'/data.txt', print_r($result, true), FILE_APPEND); // //file_put_contents($_SERVER['DOCUMENT_ROOT'].'/data.txt', print_r($results->results, true), FILE_APPEND); // if (isset($result->results->locations[0])) { // $id = $result->results->locations[0]->id; // file_put_contents($_SERVER['DOCUMENT_ROOT'].'/data.txt', 'id='.$id, FILE_APPEND); // $url = 'https://yasen.hotellook.com/tp/public/widget_location_dump.json'; // $params = [ // 'currency' => 'usd', // 'language' => 'ru', // 'limit' => 100, // 'id' => $id, // 'type' => 'popularity', // 'check_in' => $request->get_param('start_date'), // 'check_out' => $request->get_param('end_date'), // 'token' => $travelpayouts_token, // ]; // $ch = curl_init($url.'?' . http_build_query($params)); // curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // curl_setopt($ch, CURLOPT_HEADER, false); // $result = curl_exec($ch); // $result = json_decode($result); // curl_close($ch); // //file_put_contents($_SERVER['DOCUMENT_ROOT'].'/data.txt', print_r($result, true), FILE_APPEND); // } else { // $result = false; // } // //file_put_contents($_SERVER['DOCUMENT_ROOT'].'/data.txt', print_r($result, true), FILE_APPEND); // return $result; // } function get_city_id($city, $token) { $url = 'https://engine.hotellook.com/api/v2/lookup.json'; $params = [ 'query' => $city, 'lang' => 'ru', 'lookFor' => 'city', 'limit' => 1, 'token' => $token, ]; $ch = curl_init($url . '?' . http_build_query($params)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_HEADER, false); $result = curl_exec($ch); curl_close($ch); $result = json_decode($result, true); if (isset($result['results']['locations'][0]['id'])) { return $result['results']['locations'][0]['id']; } else { return false; } } function start_hotel_search($location, $check_in, $check_out, $adults_count, $token, $customer_ip, $marker, $iata = 'MOW') { $url = 'https://engine.hotellook.com/api/v2/search/start.json'; $params = [ 'cityId' => $location, 'checkIn' => $check_in, 'checkOut' => $check_out, 'adultsCount' => $adults_count, 'customerIP' => $customer_ip, 'currency' => 'USD', 'lang' => 'ru', 'waitForResult' => 0, 'marker' => $marker, 'childrenCount' => 1, 'childAge' => 10, 'iata' => $iata, ]; // Correct signature string construction $signature_string = "$token:$marker:$adults_count:$check_in:$check_out:10:1:$location:USD:$customer_ip:$iata:ru:0"; $params['signature'] = md5($signature_string); // Log all variables for signature file_put_contents('debug_log.txt', "Token: $token\n", FILE_APPEND); file_put_contents('debug_log.txt', "Marker: $marker\n", FILE_APPEND); file_put_contents('debug_log.txt', "Adults Count: $adults_count\n", FILE_APPEND); file_put_contents('debug_log.txt', "Check-in: $check_in\n", FILE_APPEND); file_put_contents('debug_log.txt', "Check-out: $check_out\n", FILE_APPEND); file_put_contents('debug_log.txt', "Child Age 1: 10\n", FILE_APPEND); file_put_contents('debug_log.txt', "Children Count: 1\n", FILE_APPEND); file_put_contents('debug_log.txt', "Currency: USD\n", FILE_APPEND); file_put_contents('debug_log.txt', "Customer IP: $customer_ip\n", FILE_APPEND); file_put_contents('debug_log.txt', "IATA: $iata\n", FILE_APPEND); file_put_contents('debug_log.txt', "Location: $location\n", FILE_APPEND); file_put_contents('debug_log.txt', "Lang: ru\n", FILE_APPEND); file_put_contents('debug_log.txt', "Wait For Result: 0\n", FILE_APPEND); file_put_contents('debug_log.txt', "Generated Signature String: $signature_string\n", FILE_APPEND); file_put_contents('debug_log.txt', "Generated Signature: " . $params['signature'] . "\n", FILE_APPEND); $ch = curl_init($url . '?' . http_build_query($params)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_HEADER, false); $result = curl_exec($ch); $curl_info = curl_getinfo($ch); // Get curl info $curl_error = curl_error($ch); // Get curl error if any curl_close($ch); $result = json_decode($result, true); if (isset($result['searchId'])) { return $result['searchId']; } else { // Log request and response for debugging file_put_contents('debug_log.txt', "Request URL: " . $url . '?' . http_build_query($params) . "\n", FILE_APPEND); file_put_contents('debug_log.txt', "Response: " . print_r($result, true) . "\n", FILE_APPEND); file_put_contents('debug_log.txt', "Curl Info: " . print_r($curl_info, true) . "\n", FILE_APPEND); file_put_contents('debug_log.txt', "Curl Error: " . $curl_error . "\n", FILE_APPEND); return false; } } function get_hotel_search_results($search_id, $token, $marker) { $url = 'https://engine.hotellook.com/api/v2/search/getResult.json'; $params = [ 'searchId' => $search_id, 'limit' => 10, 'offset' => 0, 'sortBy' => 'price', 'sortAsc' => 1, 'roomsCount' => 0, 'marker' => $marker, ]; $signature_string = "$token:$marker:10:0:0:$search_id:1:price"; $params['signature'] = md5($signature_string); // Log all variables for signature file_put_contents('debug_log.txt', "Token: $token\n", FILE_APPEND); file_put_contents('debug_log.txt', "Marker: $marker\n", FILE_APPEND); file_put_contents('debug_log.txt', "Limit: 10\n", FILE_APPEND); file_put_contents('debug_log.txt', "Offset: 0\n", FILE_APPEND); file_put_contents('debug_log.txt', "Rooms Count: 0\n", FILE_APPEND); file_put_contents('debug_log.txt', "Search ID: $search_id\n", FILE_APPEND); file_put_contents('debug_log.txt', "Sort Asc: 1\n", FILE_APPEND); file_put_contents('debug_log.txt', "Sort By: price\n", FILE_APPEND); file_put_contents('debug_log.txt', "Generated Signature String: $signature_string\n", FILE_APPEND); file_put_contents('debug_log.txt', "Generated Signature: " . $params['signature'] . "\n", FILE_APPEND); $ch = curl_init($url . '?' . http_build_query($params)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_HEADER, false); $result = curl_exec($ch); curl_close($ch); $result = json_decode($result, true); return $result; } add_action('rest_api_init', function () { register_rest_route('hotels/v1', '/hotels/', array( 'methods' => 'GET', 'callback' => 'hotels_search', )); }); function hotels_search($request) { $travelpayouts_token = '6d0c907fad90bb689a5db94d75b3789d'; $marker = '402943'; $customer_ip = $_SERVER['REMOTE_ADDR']; // Correct the iata code parameter $city = $request->get_param('city') ?? 'MOW'; $check_in = $request->get_param('start_date'); $check_out = $request->get_param('end_date'); $adults_count = $request->get_param('adults_count') ?? 1; // Default to 1 if not provided // Debugging output for city ID retrieval $city_id = get_city_id($city, $travelpayouts_token); if (!$city_id) { file_put_contents('debug_log.txt', "City ID retrieval failed for city: $city\n", FILE_APPEND); return array('error' => 'City not found', 'debug' => 'City ID retrieval failed'); } // Debugging output for search initiation $search_id = start_hotel_search($city_id, $check_in, $check_out, $adults_count, $travelpayouts_token, $customer_ip, $marker, $city); if (!$search_id) { file_put_contents('debug_log.txt', "Hotel search initiation failed for city_id: $city_id\n", FILE_APPEND); return array('error' => 'Hotel search failed', 'debug' => 'Search initiation failed'); } // Fetch search results $result = get_hotel_search_results($search_id, $travelpayouts_token, $marker); if (isset($result['status']) && $result['status'] == 'ok') { return $result; } else { file_put_contents('debug_log.txt', "Search results retrieval failed for search_id: $search_id\n", FILE_APPEND); return array('error' => 'Hotel search results retrieval failed', 'debug' => 'Search results retrieval failed'); } } Виза цифрового кочевника Португалия | TravCave
ТрэвКейв
Первый в Рунете портал, объединяющий номадов по всему миру 🌎

Мы о путешествиях, о городах, о работе на удаленке. TravCave - это место, где каждый сможет стать блогером и рассказать свою историю.

ГлавнаяСтатьиНаконец-то! Виза цифрового кочевника Португалия. Но...

Наконец-то! Виза цифрового кочевника Португалия. Но…

1009 0

Португалия с ее шумными городами, отличной погодой, морем и низкой стоимостью жизни, невероятно популярна среди цифровых кочевников. Она часто занимает первые строчки в списках идеальных мест для удаленной работы, особенно Лиссабон, Порту и Мадейра. Как результат, Португалия наконец-то запустила давно ожидаемую визу цифрового кочевника, по которой удаленные работники могут жить и работать в стране год. Digital nomad visa уже вступила в силу и была выдана 200 заявителям всего за два месяца. Она заменила существующую визу «D7» — популярный вид на жительство в Европе, предназначенный для пенсионеров и лиц, получающих «пассивный доход».

Однако, чтобы соответствовать требованиям, заявители должны зарабатывать не менее 2800 евро в месяц, что в четыре раза превышает минимальную заработную плату в Португалии. Это значительное увеличение требований к заработку по сравнению со схемой D7, по которой заявителям нужно показать всего 822,50 евро в месяц. Однако эти доходы должны поступать из «пассивных» источников, таких как аренда или инвестиции. В то время, как новая виза, официально именуемая «резидентская виза для осуществления профессиональной деятельности, предоставляемой удаленно за пределами национальной территории», предназначена для работающих специалистов.

В Португалии существует два типа виз Digital Nomad Visa.

Вы можете подать заявление на получение визы временного пребывания (Digital Nomad Temporary Stay Visa) или визы постоянного проживания (Digital Nomad Residence Visa).

Временную визу проще получить, и она позволяет вам находиться в Португалии 1 год с возможностью продления. Вам разрешено работать фрилансером или владельцем онлайн-бизнеса в течение этого периода, а также свободно путешествовать по Португалии и за ее пределы.

Вы также можете подать заявление на получение резидентской визы цифрового кочевника (Digital Nomad Residence Visa), если хотите остаться в Португалии на более длительный срок. Это идеальный вариант, если вы хотите получить вид на жительство или начать путь к португальскому гражданству.

Для получения визы Digital Nomad Residence, наряду с требованием дохода 2800 евро в месяц, вам потребуются:

  • ИНН и банковский счет в Португалии
  • Подтверждение налогового резидентства (12 месяцев)
  • Трудовой договор за пределами Португалии или контракт фрилансера
  • Платежные ведомости

Как получить визу цифрового кочевника Португалии?

Сначала вы подаете заявление в ближайшее консульство страны вашего гражданства или постоянного проживания. Если ваша заявка будет одобрена, посольство выдаст вам двукратную визу, действительную в течение четырех месяцев. С этой визой вы въедете в Португалию и начнете прохождение второго этапа – получения вида на жительство в МИД Португалии (SEF).

Комментарии 0
Первый в Рунете портал для цифровых кочевников (digital nomads)


    Привет! Я из Питера и
    расскажу тебе о городе

    Знаю много мест в Риме —
    заходи ко мне в профиль
    оставайтесь
    с нами
    и узнавайте новое
    Но сплочённость команды профессионалов
    говорит о возможностях направлений.
    Нажимая кнопку “Подписаться”, я соглашаюсь с условиями
    политики конфиденциальности