ID, * $post->post_title * ); */ if (!defined('ABSPATH')) { exit; } define('RUTUBE_API', 'https://rutube.ru/api'); /** * Шаг 1: загрузить видео в RUTUBE. * * @param string $video_url HTTPS-ссылка на видеофайл на вашем CDN * @param int $article_id ID поста WordPress (вернётся в callback в extra) * @param string $title Название ролика * @return string|WP_Error временный video_id (финальный придёт в callback) или ошибка */ function rutube_upload_video($video_url, $article_id, $title) { $callback_url = home_url('/wp-json/rutube/v1/callback'); if (defined('RUTUBE_CALLBACK_SECRET')) { $callback_url = add_query_arg('secret', RUTUBE_CALLBACK_SECRET, $callback_url); } $response = wp_remote_post(RUTUBE_API . '/video/', [ 'headers' => [ 'Authorization' => 'Token ' . RUTUBE_TOKEN, ], 'body' => [ 'url' => $video_url, 'callback_url' => $callback_url, 'errback_url' => home_url('/wp-json/rutube/v1/error'), 'title' => mb_substr($title, 0, 100), 'category_id' => 13, 'extra' => wp_json_encode(['article_id' => (string) $article_id]), ], 'timeout' => 30, ]); if (is_wp_error($response)) { error_log('[RUTUBE] upload failed: ' . $response->get_error_message()); return $response; } $data = json_decode(wp_remote_retrieve_body($response), true); $video_id = $data['video_id'] ?? null; if (!$video_id) { return new WP_Error('rutube_no_video_id', 'No video_id in response', $data); } // Сохраняем pending-связку в post_meta update_post_meta($article_id, '_rutube_video_id', $video_id); update_post_meta($article_id, '_rutube_status', 'pending'); return $video_id; } /** * Регистрируем callback endpoint /wp-json/rutube/v1/callback */ add_action('rest_api_init', function () { register_rest_route('rutube/v1', '/callback', [ 'methods' => 'POST', 'callback' => 'rutube_handle_callback', 'permission_callback' => '__return_true', // защита через secret внутри handler ]); register_rest_route('rutube/v1', '/error', [ 'methods' => 'POST', 'callback' => 'rutube_handle_error', 'permission_callback' => '__return_true', ]); }); /** * Шаг 3: callback от RUTUBE после успешной конвертации. */ function rutube_handle_callback(WP_REST_Request $request) { // Проверяем secret if (defined('RUTUBE_CALLBACK_SECRET') && $request->get_param('secret') !== RUTUBE_CALLBACK_SECRET) { return new WP_Error('forbidden', 'Invalid secret', ['status' => 403]); } $payload = $request->get_json_params(); $video_id = $payload['id'] ?? null; $article_id = $payload['session']['extra']['article_id'] ?? null; if (!$video_id || !$article_id) { return new WP_Error('bad_request', 'Missing id or extra.article_id', ['status' => 400]); } // Проверяем что мы помним эту связку $known_video_id = get_post_meta($article_id, '_rutube_video_id', true); if (!$known_video_id) { error_log("[RUTUBE] callback for unknown article_id=$article_id"); return new WP_Error('not_found', 'article_id not found', ['status' => 404]); } update_post_meta($article_id, '_rutube_video_id', $video_id); update_post_meta($article_id, '_rutube_status', 'ready'); update_post_meta($article_id, '_rutube_embed_url', $payload['embed_url'] ?? ''); return ['ok' => true]; } function rutube_handle_error(WP_REST_Request $request) { $payload = $request->get_json_params(); $article_id = $payload['session']['extra']['article_id'] ?? null; if ($article_id) { update_post_meta($article_id, '_rutube_status', 'error'); } error_log('[RUTUBE] error for article_id=' . $article_id . ': ' . wp_json_encode($payload)); return ['ok' => true]; } /** * Шаг 4: helper для шаблонов - вернуть HTML embed для статьи. * * Использование в single.php: * = rutube_render_video_for_post($post->ID); ?> */ function rutube_render_video_for_post($post_id) { $status = get_post_meta($post_id, '_rutube_status', true); if ($status !== 'ready') { return ''; // ещё конвертируется или ошибка } $video_id = get_post_meta($post_id, '_rutube_video_id', true); if (!$video_id) { return ''; } $dist = defined('RUTUBE_DIST') ? RUTUBE_DIST : ''; return sprintf( '
', esc_attr($video_id), esc_attr($dist) ); } /** * Подключаем wrapper-скрипт один раз на странице. */ add_action('wp_footer', function () { $dist = defined('RUTUBE_DIST') ? RUTUBE_DIST : ''; if ($dist) { echo ''; } echo ''; }, 99);