0 ? $h . ":" : "" ) . ( ( $m < 10 ? "0" : "" ) . $m . ":" ) . ( $s < 10 ? "0" : "" ) . $s ); } /** * Extract iframe src from the given HTML string. * * @since 1.0.0 * @param string $html HTML string. * @return string $src Iframe URL. */ function aiovg_extract_iframe_src( $html ) { $src = ''; if ( ! empty( $html ) && strpos( $html, ' $value ) { if ( $parameter_data !== '' ) { $parameter_data .= '&'; } $parameter_data_url .= '&'; $parameter_data .= $key . '=' . $value; $parameter_data_url .= $key . '=' . urlencode( $value ); } // Create the base string for token generation $hashable_base = $security_key . $signature_path . $expires; if ( ! empty( $user_ip ) ) { $hashable_base .= $user_ip; } $hashable_base .= $parameter_data; // Generate the token using SHA-256 and encode it $token = hash( 'sha256', $hashable_base, true ); $token = base64_encode( $token ); $token = strtr( $token, '+/', '-_' ); $token = str_replace( '=', '', $token ); // Build the final signed URL based on token type if ( $is_directory_token ) { $signed_url = "{$url_scheme}://{$url_host}/bcdn_token={$token}&expires={$expires}{$parameter_data_url}{$url_path}"; } else { $signed_url = "{$url_scheme}://{$url_host}{$url_path}?token={$token}{$parameter_data_url}&expires={$expires}"; } // Allow customization via filter and return final signed URL return apply_filters( 'aiovg_bunny_stream_signed_url', $signed_url, $url, $video_id ); } /** * Get Dailymotion ID from URL. * * @since 1.5.0 * @param string $url Dailymotion video URL. * @return string $id Dailymotion video ID. */ function aiovg_get_dailymotion_id_from_url( $url ) { $id = ''; if ( preg_match( '!^.+dailymotion\.com/(video|hub)/([^_]+)[^#]*(#video=([^_&]+))?|(dai\.ly/([^_]+))!', $url, $m ) ) { if ( isset( $m[6] ) ) { $id = $m[6]; } if ( isset( $m[4] ) ) { $id = $m[4]; } $id = $m[2]; } return $id; } /** * Get Dailymotion image from URL. * * @since 1.5.0 * @param string $url Dailymotion video URL. * @param bool $force_refresh Skip the cache and fetch fresh data. Default false. * @return string Dailymotion image URL. */ function aiovg_get_dailymotion_image_url( $url, $force_refresh = false ) { $data = aiovg_get_dailymotion_oembed_data( $url, $force_refresh ); return $data['thumbnail_url']; } /** * Get Dailymotion data using oEmbed. * * @since 3.8.4 * @param string $url Dailymotion URL. * @param bool $force_refresh Skip the cache and fetch fresh data. Default false. * @return string $response Dailymotion oEmbed response data. */ function aiovg_get_dailymotion_oembed_data( $url, $force_refresh = false ) { $response = array( 'thumbnail_url' => '', 'duration' => '' ); $cache_key = 'aiovg_' . md5( $url ); if ( ! $force_refresh ) { $cache_value = get_transient( $cache_key ); if ( is_array( $cache_value ) ) { $response = array_merge( $response, $cache_value ); return $response; } } $id = aiovg_get_dailymotion_id_from_url( $url ); if ( ! empty( $id ) ) { $api_response = wp_remote_get( 'https://api.dailymotion.com/video/' . $id . '?fields=thumbnail_large_url,thumbnail_medium_url,duration', array( 'sslverify' => false ) ); if ( ! is_wp_error( $api_response ) ) { $api_response = json_decode( $api_response['body'] ); if ( isset( $api_response->thumbnail_large_url ) ) { $response['thumbnail_url'] = $api_response->thumbnail_large_url; } else { $response['thumbnail_url'] = $api_response->thumbnail_medium_url; } if ( isset( $api_response->duration ) ) { $response['duration'] = $api_response->duration; } } else { // error_log( $api_response->get_error_message() ); } } if ( ! empty( $response['thumbnail_url'] ) ) { set_transient( $cache_key, $response, DAY_IN_SECONDS ); } return $response; } /** * Get Dailymotion video duration from URL. * * @since 3.8.4 * @param string $url Dailymotion video URL. * @return string Video duration. */ function aiovg_get_dailymotion_video_duration( $url ) { $data = aiovg_get_dailymotion_oembed_data( $url ); return $data['duration']; } /** * Get video duration from the Third-Party Player Code. * * @since 3.8.4 * @param string $embedcode Player Code. * @return string $duration Video duration. */ function aiovg_get_embedcode_video_duration( $embedcode ) { $duration = ''; $iframe_src = aiovg_extract_iframe_src( $embedcode ); if ( $iframe_src ) { // Vimeo if ( false !== strpos( $iframe_src, 'vimeo.com' ) ) { $duration = aiovg_get_vimeo_video_duration( $iframe_src ); } // Dailymotion elseif ( false !== strpos( $iframe_src, 'dailymotion.com' ) ) { $duration = aiovg_get_dailymotion_video_duration( $iframe_src ); } // Rumble elseif ( false !== strpos( $iframe_src, 'rumble.com' ) ) { $duration = aiovg_get_rumble_video_duration( $iframe_src ); } } // Return return $duration; } /** * Get image from the Third-Party Player Code. * * @since 1.0.0 * @param string $embedcode Player Code. * @param bool $force_refresh Skip the cache and fetch fresh data. Default false. * @return string $url Image URL. */ function aiovg_get_embedcode_image_url( $embedcode, $force_refresh = false ) { $url = ''; $iframe_src = aiovg_extract_iframe_src( $embedcode ); if ( $iframe_src ) { // YouTube if ( false !== strpos( $iframe_src, 'youtube.com' ) || false !== strpos( $iframe_src, 'youtu.be' ) ) { $url = aiovg_get_youtube_image_url( $iframe_src ); } // Vimeo elseif ( false !== strpos( $iframe_src, 'vimeo.com' ) ) { $url = aiovg_get_vimeo_image_url( $iframe_src, $force_refresh ); } // Dailymotion elseif ( false !== strpos( $iframe_src, 'dailymotion.com' ) ) { $url = aiovg_get_dailymotion_image_url( $iframe_src, $force_refresh ); } // Rumble elseif ( false !== strpos( $iframe_src, 'rumble.com' ) ) { $url = aiovg_get_rumble_image_url( $iframe_src, $force_refresh ); } } // Return image url return $url; } /** * Get Rumble image from URL. * * @since 3.8.4 * @param string $url Rumble video URL. * @param bool $force_refresh Skip the cache and fetch fresh data. Default false. * @return string Rumble image URL. */ function aiovg_get_rumble_image_url( $url, $force_refresh = false ) { $data = aiovg_get_rumble_oembed_data( $url, $force_refresh ); return $data['thumbnail_url']; } /** * Get Rumble data using oEmbed. * * @since 2.6.3 * @param string $url Rumble URL. * @param bool $force_refresh Skip the cache and fetch fresh data. Default false. * @return string $response Rumble oEmbed response data. */ function aiovg_get_rumble_oembed_data( $url, $force_refresh = false ) { $response = array( 'thumbnail_url' => '', 'duration' => '', 'html' => '' ); $cache_key = 'aiovg_' . md5( $url ); if ( ! $force_refresh ) { $cache_value = get_transient( $cache_key ); if ( is_array( $cache_value ) ) { $response = array_merge( $response, $cache_value ); return $response; } } $api_response = wp_remote_get( 'https://rumble.com/api/Media/oembed.json?url=' . urlencode( $url ) ); if ( is_array( $api_response ) && ! is_wp_error( $api_response ) ) { $api_response = json_decode( $api_response['body'] ); if ( isset( $api_response->thumbnail_url ) ) { $response['thumbnail_url'] = $api_response->thumbnail_url; } if ( isset( $api_response->duration ) ) { $response['duration'] = $api_response->duration; } if ( isset( $api_response->html ) ) { $response['html'] = $api_response->html; } } if ( ! empty( $response['thumbnail_url'] ) ) { set_transient( $cache_key, $response, DAY_IN_SECONDS ); } return $response; } /** * Get Rumble video duration from URL. * * @since 3.8.4 * @param string $url Rumble video URL. * @return string Video duration. */ function aiovg_get_rumble_video_duration( $url ) { $data = aiovg_get_rumble_oembed_data( $url ); return $data['duration']; } /** * Get Vimeo ID from URL. * * @since 3.5.0 * @param string $url Vimeo video URL. * @return string $id Vimeo video ID. */ function aiovg_get_vimeo_id_from_url( $url ) { $id = ''; // Use regexp to programmatically parse the ID. So, we can avoid an oEmbed API request if ( strpos( $url, 'player.vimeo.com' ) !== false ) { if ( preg_match( '#(?:https?://)?(?:www.)?(?:player.)?vimeo.com/(?:[a-z]*/)*([0-9]{6,11})[?]?.*#', $url, $matches ) ) { $id = $matches[1]; } } // Let us ask the Vimeo itself using their oEmbed API if ( empty( $id ) ) { $oembed = aiovg_get_vimeo_oembed_data( $url ); $id = $oembed['video_id']; } return $id; } /** * Get Vimeo image from URL. * * @since 3.5.0 * @param string $url Vimeo video URL. * @param bool $force_refresh Skip the cache and fetch fresh data. Default false. * @return string Vimeo image URL. */ function aiovg_get_vimeo_image_url( $url, $force_refresh = false ) { $data = aiovg_get_vimeo_oembed_data( $url, $force_refresh ); if ( empty( $data['video_id'] ) ) { return $data['thumbnail_url']; } $cache_key = 'aiovg_vimeo_image_' . $data['video_id']; if ( ! $force_refresh ) { $cached_image = get_transient( $cache_key ); if ( false !== $cached_image ) { return add_query_arg( 'isnew', 1, $cached_image ); } } // Find large thumbnail using the Vimeo API v2 $api_response = wp_remote_get( 'https://vimeo.com/api/v2/video/' . $data['video_id'] . '.php' ); if ( ! is_wp_error( $api_response ) ) { $api_response = maybe_unserialize( $api_response['body'] ); if ( is_array( $api_response ) && isset( $api_response[0]['thumbnail_large'] ) ) { $data['thumbnail_url'] = $api_response[0]['thumbnail_large']; } } // Get images from private videos if ( empty( $data['thumbnail_url'] ) ) { $api_settings = aiovg_get_option( 'aiovg_api_settings' ); if ( isset( $api_settings['vimeo_access_token'] ) && ! empty( $api_settings['vimeo_access_token'] ) ) { $args = array( 'headers' => array( 'Authorization' => 'Bearer ' . sanitize_text_field( $api_settings['vimeo_access_token'] ) ) ); $api_response = wp_remote_get( 'https://api.vimeo.com/videos/' . $data['video_id'] . '/pictures', $args ); if ( is_array( $api_response ) && ! is_wp_error( $api_response ) ) { $api_response = json_decode( $api_response['body'] ); if ( isset( $api_response->data ) ) { $bypass = false; foreach ( $api_response->data as $item ) { foreach ( $item->sizes as $picture ) { $data['thumbnail_url'] = $picture->link; if ( $picture->width >= 400 ) { $bypass = true; break; } } if ( $bypass ) break; } } } } } if ( ! empty( $data['thumbnail_url'] ) ) { set_transient( $cache_key, $data['thumbnail_url'], DAY_IN_SECONDS ); $data['thumbnail_url'] = add_query_arg( 'isnew', 1, $data['thumbnail_url'] ); } return $data['thumbnail_url']; } /** * Get Vimeo data using oEmbed. * * @since 1.6.6 * @param string $url Vimeo URL. * @param bool $force_refresh Skip the cache and fetch fresh data. Default false. * @return string $response Vimeo oEmbed response data. */ function aiovg_get_vimeo_oembed_data( $url, $force_refresh = false ) { $response = array( 'video_id' => '', 'thumbnail_url' => '', 'duration' => '', 'html' => '' ); $cache_key = 'aiovg_' . md5( $url ); if ( ! $force_refresh ) { $cache_value = get_transient( $cache_key ); if ( is_array( $cache_value ) ) { $response = array_merge( $response, $cache_value ); return $response; } } $api_response = wp_remote_get( 'https://vimeo.com/api/oembed.json?url=' . urlencode( $url ) ); if ( is_array( $api_response ) && ! is_wp_error( $api_response ) ) { $api_response = json_decode( $api_response['body'] ); if ( isset( $api_response->video_id ) ) { $response['video_id'] = $api_response->video_id; } if ( isset( $api_response->thumbnail_url ) ) { $response['thumbnail_url'] = $api_response->thumbnail_url; } if ( isset( $api_response->duration ) ) { $response['duration'] = $api_response->duration; } if ( isset( $api_response->html ) ) { $response['html'] = $api_response->html; } } // Fallback to our old method to get the Vimeo ID if ( empty( $response['video_id'] ) ) { $is_vimeo = preg_match( '/vimeo\.com/i', $url ); if ( $is_vimeo ) { $response['video_id'] = preg_replace( '/[^\/]+[^0-9]|(\/)/', '', rtrim( $url, '/' ) ); } } if ( ! empty( $response['video_id'] ) ) { set_transient( $cache_key, $response, DAY_IN_SECONDS ); } return $response; } /** * Get Vimeo video duration from URL. * * @since 3.8.4 * @param string $url Vimeo video URL. * @return string Video duration. */ function aiovg_get_vimeo_video_duration( $url ) { $data = aiovg_get_vimeo_oembed_data( $url ); return $data['duration']; } /** * Get YouTube ID from URL. * * @since 1.0.0 * @param string $url YouTube video URL. * @return string $id YouTube video ID. */ function aiovg_get_youtube_id_from_url( $url ) { $id = ''; $url = parse_url( $url ); if ( 0 === strcasecmp( $url['host'], 'youtu.be' ) ) { $id = substr( $url['path'], 1 ); } elseif ( 0 === strcasecmp( $url['host'], 'www.youtube.com' ) || 0 === strcasecmp( $url['host'], 'youtube.com' ) ) { if ( isset( $url['query'] ) ) { parse_str( $url['query'], $url['query'] ); if ( isset( $url['query']['v'] ) ) { $id = $url['query']['v']; } } if ( empty( $id ) ) { $url['path'] = explode( '/', substr( $url['path'], 1 ) ); if ( in_array( $url['path'][0], array( 'e', 'embed', 'v', 'shorts', 'live' ) ) ) { $id = $url['path'][1]; } } } return $id; } /** * Get YouTube image from URL. * * @since 1.0.0 * @param string $url YouTube video URL. * @return string $url YouTube image URL. */ function aiovg_get_youtube_image_url( $url ) { $id = aiovg_get_youtube_id_from_url( $url ); $url = ''; if ( ! empty( $id ) ) { $url = "https://img.youtube.com/vi/$id/maxresdefault.jpg"; $response = wp_remote_get( $url ); if ( 200 != wp_remote_retrieve_response_code( $response ) ) { $url = "https://img.youtube.com/vi/$id/mqdefault.jpg"; } } return $url; } /** * Check if Bunny Stream hosting is enabled and return settings. * * @since 4.2.0 * @return array|false Returns the Bunny Stream settings array if all conditions are met; otherwise, false. */ function aiovg_has_bunny_stream_enabled() { $settings = aiovg_get_option( 'aiovg_bunny_stream_settings' ); // Basic Bunny Stream setup check if ( empty( $settings['enable_bunny_stream'] ) || empty( $settings['api_key'] ) || empty( $settings['library_id'] ) || empty( $settings['cdn_hostname'] ) ) { return false; } return $settings; } /** * Resolve YouTube URLs. * * @since 2.5.6 * @param string $url YouTube URL. * @return string $url Resolved YouTube URL. */ function aiovg_resolve_youtube_url( $url ) { if ( false !== strpos( $url, '/shorts/' ) || false !== strpos( $url, '/live/' ) ) { $id = aiovg_get_youtube_id_from_url( $url ); if ( ! empty( $id ) ) { $url = 'https://www.youtube.com/watch?v=' . $id; } } return $url; }