diff options
| author | Miles Wilson <miles@pro.mileswilson.net> | 2025-05-15 15:47:09 -0400 |
|---|---|---|
| committer | Miles Wilson <miles@pro.mileswilson.net> | 2025-05-15 15:47:09 -0400 |
| commit | bf6c05629b894908562fe93fb6f38728e4df6e98 (patch) | |
| tree | 972e906854cfa822dc6055093630731027c9f887 /spinitron-now-playing.php | |
| download | spinitron-now-playing-main.tar.gz spinitron-now-playing-main.tar.bz2 spinitron-now-playing-main.zip | |
Diffstat (limited to '')
| -rw-r--r-- | spinitron-now-playing.php | 294 |
1 files changed, 294 insertions, 0 deletions
diff --git a/spinitron-now-playing.php b/spinitron-now-playing.php new file mode 100644 index 0000000..53b51ce --- /dev/null +++ b/spinitron-now-playing.php @@ -0,0 +1,294 @@ +<?php +/* +Plugin Name: Spinitron Now Playing +Description: Fetches and caches now playing data from Spinitron API. Provides a REST endpoint at /wp-json/spinitron/v1/now-playing. +Version: 1.0 +Author: Miles Wilson +*/ + +// Prevent direct access +defined( 'ABSPATH' ) || exit; + +// Add admin menu +add_action( 'admin_menu', 'spinitron_add_admin_menu' ); +add_action( 'admin_init', 'spinitron_settings_init' ); + +function spinitron_add_admin_menu() { + add_options_page( + 'Spinitron Now Playing Settings', + 'Spinitron Now Playing', + 'manage_options', + 'spinitron-now-playing', + 'spinitron_options_page_html' + ); +} + +function spinitron_settings_init() { + register_setting( 'spinitron', 'spinitron_api_key', array( + 'sanitize_callback' => 'sanitize_text_field', + ) ); + register_setting( 'spinitron', 'spinitron_cache_duration', array( + 'sanitize_callback' => 'absint', + ) ); + register_setting( 'spinitron', 'spinitron_audio_stream_url', array( + 'sanitize_callback' => 'esc_url_raw', + ) ); + + add_settings_section( + 'spinitron_section', + 'API Settings', + 'spinitron_section_callback', + 'spinitron' + ); + + add_settings_field( + 'spinitron_api_key', + 'API Key', + 'spinitron_api_key_render', + 'spinitron', + 'spinitron_section' + ); + + add_settings_field( + 'spinitron_cache_duration', + 'Cache Duration (seconds)', + 'spinitron_cache_duration_render', + 'spinitron', + 'spinitron_section' + ); + + add_settings_field( + 'spinitron_audio_stream_url', + 'Audio Stream URL', + 'spinitron_audio_stream_url_render', + 'spinitron', + 'spinitron_section' + ); +} + +function spinitron_api_key_render() { + $api_key = get_option( 'spinitron_api_key' ); + echo '<input type="text" name="spinitron_api_key" value="' . esc_attr( $api_key ) . '" class="regular-text">'; +} + +function spinitron_cache_duration_render() { + $cache_duration = get_option( 'spinitron_cache_duration', 60 ); + echo '<input type="number" name="spinitron_cache_duration" value="' . esc_attr( $cache_duration ) . '" min="1">'; +} + +function spinitron_section_callback() { + echo '<p>Enter your Spinitron API credentials and cache settings below:</p>'; +} + +function spinitron_options_page_html() { + if ( ! current_user_can( 'manage_options' ) ) return; + ?> + <div class="wrap"> + <h1>Spinitron Now Playing Settings</h1> + <form action="options.php" method="post"> + <?php + settings_fields( 'spinitron' ); + do_settings_sections( 'spinitron' ); + submit_button( 'Save Settings' ); + ?> + </form> + </div> + <?php +} + +// Register REST API endpoint +add_action( 'rest_api_init', function () { + register_rest_route( 'spinitron/v1', '/now-playing', array( + 'methods' => 'GET', + 'callback' => 'spinitron_now_playing_endpoint', + 'permission_callback' => '__return_true' + ) ); +} ); + +function spinitron_now_playing_endpoint( $request ) { + $api_key = get_option( 'spinitron_api_key' ); + $cache_duration = get_option( 'spinitron_cache_duration', 60 ); + $cache_duration = max( 1, (int) $cache_duration ); + + // Check API key + if ( empty( $api_key ) ) { + return new WP_Error( 'api_key_missing', 'Spinitron API key is not configured.', array( 'status' => 500 ) ); + } + + // Check cache + $cached_data = get_transient( 'spinitron_now_playing_data' ); + if ( $cached_data !== false ) { + return spinitron_create_response( $cached_data ); + } + + // Fetch new data + $spin_url = 'https://spinitron.com/api/spins?count=1&sort=start&direction=desc'; + $args = array( + 'headers' => array( + 'Authorization' => 'Bearer ' . $api_key, + 'Accept' => 'application/json', + 'User-Agent' => 'WordPress Spinitron Now Playing', + ), + 'timeout' => 5, + ); + + // Fetch spin data + $spin_response = wp_remote_get( $spin_url, $args ); + if ( is_wp_error( $spin_response ) ) { + $error_data = array( + 'status' => 'error', + 'error' => 'API request failed: ' . $spin_response->get_error_message(), + 'last_updated' => time(), + ); + set_transient( 'spinitron_now_playing_data', $error_data, $cache_duration ); + return spinitron_create_response( $error_data ); + } + + $spin_body = wp_remote_retrieve_body( $spin_response ); + $spin_data = json_decode( $spin_body, true ); + + if ( empty( $spin_data['items'] ) ) { + $error_data = array( + 'status' => 'error', + 'error' => 'No spins found in response', + 'last_updated' => time(), + ); + set_transient( 'spinitron_now_playing_data', $error_data, $cache_duration ); + return spinitron_create_response( $error_data ); + } + + $spin_item = $spin_data['items'][0]; + + // Fetch playlist data + if ( empty( $spin_item['_links']['playlist']['href'] ) ) { + $error_data = array( + 'status' => 'error', + 'error' => 'Spin data missing playlist link', + 'spin_data' => $spin_item, + 'last_updated' => time(), + ); + set_transient( 'spinitron_now_playing_data', $error_data, $cache_duration ); + return spinitron_create_response( $error_data ); + } + + $playlist_url = $spin_item['_links']['playlist']['href']; + $playlist_response = wp_remote_get( $playlist_url, $args ); + + if ( is_wp_error( $playlist_response ) ) { + $error_data = array( + 'status' => 'error', + 'error' => 'Playlist request failed: ' . $playlist_response->get_error_message(), + 'spin_data' => $spin_item, + 'last_updated' => time(), + ); + set_transient( 'spinitron_now_playing_data', $error_data, $cache_duration ); + return spinitron_create_response( $error_data ); + } + + $playlist_body = wp_remote_retrieve_body( $playlist_response ); + $playlist_data = json_decode( $playlist_body, true ); + + // Successful response + $result = array( + 'status' => 'ok', + 'spin_data' => $spin_item, + 'playlist_data' => $playlist_data, + 'error' => null, + 'last_updated' => time(), + ); + + set_transient( 'spinitron_now_playing_data', $result, $cache_duration ); + return spinitron_create_response( $result ); +} + +function spinitron_create_response( $data ) { + $response = new WP_REST_Response( $data ); + $response->header( 'Access-Control-Allow-Origin', '*' ); + $response->header( 'Cache-Control', 'no-cache, max-age=0' ); + return $response; +} + +// Add shortcode for player +add_shortcode('spinitron_player', 'spinitron_player_shortcode'); + +function spinitron_player_shortcode() { + $audio_url = get_option('spinitron_audio_stream_url'); + + ob_start(); ?> + <div class="spinitron-player"> + <button class="spinitron-play-button" id="spinitronPlayButton"> + <span>▶</span> <span class="play-text">Play</span> + </button> + + <div class="spinitron-metadata" id="spinitronMetadata"> + <div class="spinitron-song-info"> + <div class="spinitron-now-playing">NOW PLAYING</div> + <div class="spinitron-title"> + <a href="https://spinitron.com/WVAU/" target="_blank" id="spinitronSongTitle" style="color: #ccc">-</a> + </div> + <div id="spinitronArtistAlbum"> + by <a href="https://spinitron.com/WVAU/" target="_blank" id="spinitronArtist" style="color: #ccc">-</a> + from <a href="https://spinitron.com/WVAU/" target="_blank" id="spinitronRelease" style="color: #ccc">-</a> + </div> + </div> + + <div class="spinitron-show-info"> + <div class="spinitron-now-playing">CURRENT SHOW</div> + <div class="spinitron-title"> + <a href="https://spinitron.com/WVAU/" target="_blank" id="spinitronShowTitle" style="color: #ccc">-</a> + </div> + <div id="spinitronEpisodeName"> + <a href="https://spinitron.com/WVAU/" target="_blank" id="spinitronEpisode" style="color: #ccc">-</a> + </div> + </div> + </div> + + <audio id="spinitronAudioPlayer" src="<?php echo esc_url($audio_url); ?>"></audio> + </div> + <?php + return ob_get_clean(); +} + +function spinitron_audio_stream_url_render() { + $audio_url = get_option('spinitron_audio_stream_url'); + echo '<input type="url" name="spinitron_audio_stream_url" value="' . esc_url($audio_url) . '" class="regular-text">'; +} + +// Enqueue assets +add_action('wp_enqueue_scripts', 'spinitron_enqueue_assets'); + +function spinitron_enqueue_assets() { + wp_enqueue_style('spinitron-player', plugins_url('player.css', __FILE__)); + wp_enqueue_script('spinitron-player', plugins_url('player.js', __FILE__), array(), false, true); + + wp_localize_script('spinitron-player', 'spinitronConfig', array( + 'endpoint' => rest_url('spinitron/v1/now-playing'), + 'cacheDuration' => get_option('spinitron_cache_duration', 60) * 1000 + )); +} + +// Recently Played Marquee Shortcode +add_shortcode('spinitron_recently_played', 'spinitron_recently_played_shortcode'); + +function spinitron_recently_played_shortcode() { + ob_start(); ?> + <div id="spin-recent"> + <div id="ticker"> + <p> + <span id="recent-spin-template" style="display: none;"> + <a href="https://spinitron.com/WVAU/spin/{spin_id}" target="_blank" class="recent-link"> + {time} <em>“{song}”</em> + </a> + by <a href="https://spinitron.com/WVAU/artist/{artist_id}" target="_blank" class="recent-link"><b>{artist}</b></a> + from <a href="https://spinitron.com/WVAU/release/{release_id}" target="_blank" class="recent-link">{release}</a> + </span> + <span id="recent-spin-container"></span> + <span class="listen-now"> + <em><a href="<?php echo esc_url(get_option('spinitron_audio_stream_url')); ?>" target="_blank">LISTEN NOW!</a></em> + </span> + </p> + </div> + </div> + <?php + return ob_get_clean(); +} |
