From fc58992011682b9557556e9cbf975326722058e8 Mon Sep 17 00:00:00 2001 From: Sophia Atkinson Date: Fri, 20 Jun 2025 23:44:30 -0700 Subject: [PATCH] Initial commit --- LICENSE | 21 ++++ assets/css/amnp-style.css | 61 +++++++++++ nowplaying-api.php | 225 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 307 insertions(+) create mode 100644 LICENSE create mode 100644 assets/css/amnp-style.css create mode 100644 nowplaying-api.php diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..97ec8ae --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Sophia Atkinson + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/assets/css/amnp-style.css b/assets/css/amnp-style.css new file mode 100644 index 0000000..ff72f19 --- /dev/null +++ b/assets/css/amnp-style.css @@ -0,0 +1,61 @@ + .amnp #widget { + background: #2a2a2a; + padding: 20px; + border-radius: 8px; + text-align: center; + } + + .amnp #title { + font-size: 1.2rem; + margin-bottom: 8px; + font-weight: bold; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } + + .amnp #artist { + font-size: 1rem; + margin-bottom: 12px; + color: #bbb; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } + + .amnp #status { + font-size: 0.9rem; + margin-bottom: 12px; + color: #888; + } + + .amnp #cover { + width: 150px; + height: 150px; + object-fit: cover; + border-radius: 8px; + margin-bottom: 12px; + } + + .amnp #progress-container { + background: #444; + height: 8px; + border-radius: 4px; + overflow: hidden; + margin: 12px 0 6px 0; + } + + .amnp #progress-bar { + background: #F5A9B8; + height: 100%; + width: 0%; + transition: width 0.3s linear; + } + + .amnp #time-info { + font-size: 0.8rem; + color: #aaa; + display: flex; + justify-content: space-between; + font-family: monospace; + } \ No newline at end of file diff --git a/nowplaying-api.php b/nowplaying-api.php new file mode 100644 index 0000000..d0163fd --- /dev/null +++ b/nowplaying-api.php @@ -0,0 +1,225 @@ + 'POST', + 'callback' => 'nowplaying_api_handle_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'); + + 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); + } + + $file_path = plugin_dir_path(__FILE__) . 'nowplaying.json'; + + try { + $written = file_put_contents($file_path, json_encode($data, JSON_PRETTY_PRINT)); + if (!$written) 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); +} + +// === 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')); + ?> +
+

Apple Music Now Playing API Settings

+

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

+ + +
+ + + + + + +
+ +

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'] ?? ''); + ?> +

+ + +

+