'https://...'); */ function med_diag_api_url() { $url = get_option( 'med_diag_api_url', 'https://med.my-dpr.ru' ); return apply_filters( 'med_diag_api_url', untrailingslashit( $url ) ); } /** * Внутренний URL API-бэкенда (для проксирования через PHP). * По умолчанию — внутренний IP сервера, где стоит и WordPress, и API. * Можно переопределить фильтром: add_filter('med_diag_internal_url', fn() => 'http://10.0.0.5:18018'); */ function med_diag_internal_url() { $url = get_option( 'med_diag_internal_url', 'http://127.0.0.1:18018' ); return apply_filters( 'med_diag_internal_url', untrailingslashit( $url ) ); } /** * Режим подключения к бэкенду: * 'proxy' — браузер шлёт запрос на этот же WordPress, PHP проксирует на внутренний IP (по умолчанию); * 'direct' — браузер шлёт запрос напрямую на публичный URL API (нужен CORS на бэкенде). */ function med_diag_mode() { $mode = get_option( 'med_diag_mode', 'proxy' ); return apply_filters( 'med_diag_mode', in_array( $mode, array( 'proxy', 'direct' ), true ) ? $mode : 'proxy' ); } /* ─── Регистрация ассетов ─────────────────────────────────── */ add_action( 'wp_enqueue_scripts', 'med_diag_register_assets' ); function med_diag_register_assets() { wp_register_style( 'med-diag-css', MED_DIAG_PLUGIN_URL . 'assets/css/med-diag.css', array(), MED_DIAG_VERSION ); wp_register_script( 'med-diag-js', MED_DIAG_PLUGIN_URL . 'assets/js/med-diag.js', array(), MED_DIAG_VERSION, true // в футере ); wp_localize_script( 'med-diag-js', 'MED_DIAG', array( 'apiUrl' => med_diag_api_url(), 'proxyUrl' => rest_url( 'med-diag/v1' ), 'mode' => med_diag_mode(), ) ); } /* ─── Прокси на внутренний IP (REST) ──────────────────────── */ add_action( 'rest_api_init', 'med_diag_register_routes' ); function med_diag_register_routes() { // Анализ: браузер → этот WordPress → внутренний IP бэкенда register_rest_route( 'med-diag/v1', '/analyze', array( 'methods' => 'POST', 'permission_callback' => '__return_true', 'callback' => 'med_diag_proxy_analyze', ) ); // Скачивания (PDF/DOCX/видео): /download// register_rest_route( 'med-diag/v1', '/download/(?P[^/]+)/(?P[a-z]+)', array( 'methods' => 'GET', 'permission_callback' => '__return_true', 'callback' => 'med_diag_proxy_download', ) ); } function med_diag_proxy_analyze( $request ) { $files = $request->get_file_params(); if ( empty( $files['video'] ) ) { return new WP_Error( 'med_diag_no_video', 'Файл video не получен', array( 'status' => 400 ) ); } $file = $files['video']; if ( $file['error'] !== UPLOAD_ERR_OK ) { return new WP_Error( 'med_diag_upload_error', 'Ошибка загрузки файла (код ' . $file['error'] . ')', array( 'status' => 400 ) ); } if ( $file['size'] > 100 * 1024 * 1024 ) { return new WP_Error( 'med_diag_too_large', 'Видео больше 100 МБ', array( 'status' => 413 ) ); } $boundary = wp_generate_password( 24, false ); $body = '--' . $boundary . "\r\n"; $body .= 'Content-Disposition: form-data; name="video"; filename="' . basename( $file['name'] ) . '"' . "\r\n"; $body .= 'Content-Type: ' . $file['type'] . "\r\n\r\n"; $body .= file_get_contents( $file['tmp_name'] ) . "\r\n"; $body .= '--' . $boundary . "--\r\n"; $response = wp_remote_post( med_diag_internal_url() . '/analyze', array( 'timeout' => 300, 'headers' => array( 'Content-Type' => 'multipart/form-data; boundary=' . $boundary ), 'body' => $body, ) ); if ( is_wp_error( $response ) ) { return new WP_Error( 'med_diag_proxy_error', 'Бэкенд недоступен: ' . $response->get_error_message(), array( 'status' => 502 ) ); } $status = wp_remote_retrieve_response_code( $response ); $data = json_decode( wp_remote_retrieve_body( $response ), true ); if ( json_last_error() !== JSON_ERROR_NONE ) { return new WP_Error( 'med_diag_bad_response', 'Некорректный ответ бэкенда', array( 'status' => 502 ) ); } return new WP_REST_Response( $data, $status ); } function med_diag_proxy_download( $request ) { $id = rawurlencode( $request['id'] ); $type = $request['type']; $response = wp_remote_get( med_diag_internal_url() . '/download/' . $id . '/' . $type, array( 'timeout' => 300, ) ); if ( is_wp_error( $response ) ) { return new WP_Error( 'med_diag_proxy_error', 'Бэкенд недоступен', array( 'status' => 502 ) ); } $status = wp_remote_retrieve_response_code( $response ); if ( $status !== 200 ) { return new WP_Error( 'med_diag_download_error', 'Ошибка скачивания (HTTP ' . $status . ')', array( 'status' => $status ) ); } $body = wp_remote_retrieve_body( $response ); $headers = wp_remote_retrieve_headers( $response ); $content_type = isset( $headers['content-type'] ) ? $headers['content-type'] : 'application/octet-stream'; $filename = 'diagnostic_' . $request['id'] . '.' . ( 'video' === $type ? 'webm' : $type ); header( 'Content-Type: ' . $content_type ); header( 'Content-Disposition: attachment; filename="' . $filename . '"' ); header( 'Content-Length: ' . strlen( $body ) ); echo $body; exit; } /* ─── Шорткод ─────────────────────────────────────────────── */ add_shortcode( 'med_diagnostics', 'med_diag_shortcode' ); function med_diag_shortcode( $atts ) { $atts = shortcode_atts( array( 'title' => '🩺 Диагностика по видео', ), $atts, 'med_diagnostics' ); wp_enqueue_style( 'med-diag-css' ); wp_enqueue_script( 'med-diag-js' ); ob_start(); ?>

Загрузите видео с лицом — получите оценку состояния здоровья

📷 Сканирование

Наведите камеру на лицо — мы сделаем 300 кадров и проведём анализ

Загрузка видео

📹

Нажмите или перетащите видео сюда

MP4, AVI, MOV, MKV • до 100 МБ • 10–15 секунд • лицо анфас

Подготовка...

📋 Результат анализа

Кадров: 0 / 300 (0%)
Держите лицо в круге, смотрите прямо в камеру, не двигайтесь
'string', 'sanitize_callback' => 'esc_url_raw', 'default' => 'https://med.my-dpr.ru', ) ); register_setting( 'med_diag_settings', 'med_diag_internal_url', array( 'type' => 'string', 'sanitize_callback' => 'esc_url_raw', 'default' => 'http://127.0.0.1:18018', ) ); register_setting( 'med_diag_settings', 'med_diag_mode', array( 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', 'default' => 'proxy', ) ); } function med_diag_settings_page() { ?>

Med Diagnostics


Использование

Вставьте шорткод [med_diagnostics] в любую страницу или запись.

Дополнительные параметры: [med_diagnostics title="Мой заголовок"]

Важно: используйте шорткод один раз на странице.