"POST", "callback" => "nowplaying_api_handle_post", "permission_callback" => "__return_true", ]); register_rest_route("nowplaying/v1", "/update/artwork", [ "methods" => "POST", "callback" => "nowplaying_api_handle_art_post", "permission_callback" => "__return_true", ]); }); function nowplaying_api_handle_post(WP_REST_Request $request) { $stored_key = get_option("nowplaying_api_key"); $auth_header = $request->get_header("authorization"); $expected_prefix = "bearer "; $auth_header_normalized = strtolower(trim($auth_header ?? "")); if ( !$auth_header || stripos($auth_header_normalized, $expected_prefix) !== 0 || substr(trim($auth_header), strlen($expected_prefix)) !== $stored_key ) { return new WP_REST_Response("Forbidden: Invalid API key.", 403); } $data = json_decode($request->get_body(), true); if ($data === null) { return new WP_REST_Response("Invalid JSON.", 400); } $file_path = plugin_dir_path(__FILE__) . "nowplaying.json"; $written = file_put_contents( $file_path, json_encode($data, JSON_PRETTY_PRINT) ); try { $written = file_put_contents( $file_path, json_encode($data, JSON_PRETTY_PRINT) ); if ($written === false) { throw new Exception(); } } catch (Exception $e) { return new WP_REST_Response("Failed to write to nowplaying.json.", 500); } return new WP_REST_Response("Now Playing updated.", 200); } function nowplaying_api_handle_art_post(WP_REST_Request $request) { $stored_key = get_option("nowplaying_api_key"); $auth_header = $request->get_header("authorization"); if (!$auth_header || $auth_header !== "Bearer $stored_key") { return new WP_REST_Response("Forbidden: Invalid API key.", 403); } $data = json_decode($request->get_body(), true); if ($data === null) { return new WP_REST_Response("Invalid JSON.", 400); } if (!isset($data["image"]) || !is_string($data["image"])) { return new WP_REST_Response( 'Missing or invalid "image" property.', 400 ); } $file_path = plugin_dir_path(__FILE__) . "nowplaying-art.json"; try { $written = file_put_contents( $file_path, json_encode($data, JSON_PRETTY_PRINT) ); if ($written === false) { throw new Exception(); } } catch (Exception $e) { return new WP_REST_Response( "Failed to write to nowplaying-art.json.", 500 ); } return new WP_REST_Response("Artwork updated.", 200); } // === Admin Settings Page === add_action("admin_menu", function () { add_options_page( "Now Playing API Settings", "Now Playing API", "manage_options", "nowplaying-api", "nowplaying_api_settings_page" ); }); function nowplaying_api_settings_page() { if (!current_user_can("manage_options")) { return; } if ( isset($_POST["nowplaying_api_key"]) && check_admin_referer("nowplaying_save_key", "nowplaying_nonce") ) { $new_key = sanitize_text_field($_POST["nowplaying_api_key"]); if (strlen($new_key) === 64) { update_option("nowplaying_api_key", $new_key); echo '

API key updated.

'; } else { echo '

API key must be exactly 64 characters.

'; } } if ( isset($_POST["generate_key"]) && check_admin_referer("nowplaying_save_key", "nowplaying_nonce") ) { $generated_key = bin2hex(random_bytes(32)); update_option("nowplaying_api_key", $generated_key); echo '

New API key generated.

'; } $current_key = get_option("nowplaying_api_key"); if (!$current_key) { $current_key = bin2hex(random_bytes(32)); update_option("nowplaying_api_key", $current_key); } $url = esc_url(site_url("/wp-json/nowplaying/v1/update")); $artwork_url = esc_url(site_url("/wp-json/nowplaying/v1/update/artwork")); ?>

Apple Music Now Playing API Settings

This is the key you will use for the web extension to communicate with this server. The POST addresses are:

Now playing Endpoint:
Artwork Endpoint:

Keep this key secret.
Must be 64 characters.

Album cover
Loading...
0:000:00
__( "Displays the current Apple Music song from your API.", "nowplaying" ), ] ); } public function widget($args, $instance) { $title = apply_filters("widget_title", $instance["title"] ?? ""); echo $args["before_widget"]; if (!empty($title)) { echo $args["before_title"] . esc_html($title) . $args["after_title"]; } echo do_shortcode("[now-playing-widget]"); echo $args["after_widget"]; } public function form($instance) { $title = esc_attr($instance["title"] ?? ""); ?>

" name="get_field_name("title") ); ?>" type="text" value="" />