summaryrefslogtreecommitdiffstats
path: root/spinitron-now-playing.php
diff options
context:
space:
mode:
authorMiles Wilson <miles@pro.mileswilson.net>2025-05-15 15:47:09 -0400
committerMiles Wilson <miles@pro.mileswilson.net>2025-05-15 15:47:09 -0400
commitbf6c05629b894908562fe93fb6f38728e4df6e98 (patch)
tree972e906854cfa822dc6055093630731027c9f887 /spinitron-now-playing.php
downloadspinitron-now-playing-main.tar.gz
spinitron-now-playing-main.tar.bz2
spinitron-now-playing-main.zip
Initial commit.HEADmain
Diffstat (limited to 'spinitron-now-playing.php')
-rw-r--r--spinitron-now-playing.php294
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();
+}