294 lines
9.7 KiB
PHP
294 lines
9.7 KiB
PHP
<?php
|
|
|
|
// Prevent direct access to the file
|
|
if (!defined('ABSPATH')) {
|
|
exit;
|
|
}
|
|
|
|
// Include necessary files
|
|
require_once(ABSPATH . 'wp-admin/includes/image.php');
|
|
require_once(ABSPATH . 'wp-admin/includes/file.php');
|
|
require_once(ABSPATH . 'wp-admin/includes/media.php');
|
|
|
|
class ScrobbleHandler {
|
|
private $auth_key;
|
|
private $option_name = 'image_scrobble_auth_key';
|
|
|
|
public function __construct() {
|
|
$this->auth_key = get_option($this->option_name);
|
|
|
|
add_action('rest_api_init', array($this, 'register_routes'));
|
|
add_action('admin_menu', array($this, 'add_admin_menu'));
|
|
add_action('admin_init', array($this, 'register_settings'));
|
|
register_activation_hook(__FILE__, array($this, 'activate_plugin'));
|
|
}
|
|
|
|
public function activate_plugin() {
|
|
// Set default AUTH_KEY if not exists
|
|
if (!get_option($this->option_name)) {
|
|
update_option($this->option_name, wp_generate_password(32, false));
|
|
}
|
|
}
|
|
|
|
public function register_routes() {
|
|
register_rest_route('image-scrobble/v1', '/create', array(
|
|
'methods' => 'POST',
|
|
'callback' => array($this, 'create_image'),
|
|
'permission_callback' => array($this, 'check_auth')
|
|
));
|
|
|
|
register_rest_route('image-scrobble/v1', '/scrobble', array(
|
|
'methods' => 'POST',
|
|
'callback' => array($this, 'scrobble'),
|
|
'permission_callback' => array($this, 'check_auth')
|
|
));
|
|
}
|
|
|
|
public function check_auth($request) {
|
|
$auth_header = $request->get_header('Authorization');
|
|
return $auth_header && $auth_header === "Bearer {$this->auth_key}";
|
|
}
|
|
|
|
public function create_image($request) {
|
|
// Retrieve the raw image data from the request body
|
|
$image_data = $request->get_body();
|
|
|
|
// Sanitize and retrieve parameters from the request
|
|
$author = sanitize_text_field($request->get_param('author'));
|
|
$album_title = sanitize_text_field($request->get_param('album_title'));
|
|
$song_title = sanitize_text_field($request->get_param('song_title')); // New parameter
|
|
|
|
// Validate required parameters
|
|
if (empty($author)) {
|
|
return new WP_Error(
|
|
'missing_author',
|
|
'Author is required.',
|
|
array('status' => 400)
|
|
);
|
|
}
|
|
|
|
// Ensure that either album_title or song_title is provided
|
|
if (empty($album_title) && empty($song_title)) {
|
|
return new WP_Error(
|
|
'missing_titles',
|
|
'Either album title or song title is required.',
|
|
array('status' => 400)
|
|
);
|
|
}
|
|
|
|
// Determine which title to use: album_title takes precedence over song_title
|
|
$title = !empty($album_title) ? $album_title : $song_title;
|
|
|
|
// Generate a hash of the image data to check for duplicates
|
|
$image_hash = md5($image_data);
|
|
|
|
// Check if an image with this hash already exists to prevent duplicates
|
|
$existing_attachment = $this->get_attachment_by_hash($image_hash);
|
|
if ($existing_attachment) {
|
|
return new WP_REST_Response(
|
|
array('url' => wp_get_attachment_url($existing_attachment->ID)),
|
|
200
|
|
);
|
|
}
|
|
|
|
// Get the upload directory information
|
|
$upload_dir = wp_upload_dir();
|
|
|
|
// Create a sanitized filename using the author and the determined title
|
|
$filename = sanitize_file_name("{$author} - {$title}.jpg");
|
|
|
|
// Ensure the filename is unique within the upload directory
|
|
$unique_filename = wp_unique_filename($upload_dir['path'], $filename);
|
|
|
|
// Construct the full file path
|
|
$file_path = trailingslashit($upload_dir['path']) . $unique_filename;
|
|
|
|
// Attempt to save the image data to the specified file path
|
|
if (file_put_contents($file_path, $image_data) === false) {
|
|
return new WP_Error(
|
|
'file_save_failed',
|
|
'Failed to save the image file.',
|
|
array('status' => 500)
|
|
);
|
|
}
|
|
|
|
// Prepare the attachment data
|
|
$attachment = array(
|
|
'post_mime_type' => 'image/jpeg',
|
|
'post_title' => "{$author} - {$title}",
|
|
'post_content' => '',
|
|
'post_status' => 'inherit'
|
|
);
|
|
|
|
// Insert the attachment into the WordPress media library
|
|
$attach_id = wp_insert_attachment($attachment, $file_path);
|
|
|
|
// Check for errors during attachment insertion
|
|
if (is_wp_error($attach_id)) {
|
|
@unlink($file_path); // Clean up the file if attachment creation failed
|
|
return $attach_id; // Return the WP_Error
|
|
}
|
|
|
|
// Generate and update attachment metadata
|
|
require_once(ABSPATH . 'wp-admin/includes/image.php');
|
|
$attach_data = wp_generate_attachment_metadata($attach_id, $file_path);
|
|
wp_update_attachment_metadata($attach_id, $attach_data);
|
|
|
|
// Save the image hash in the attachment's metadata for future duplicate checks
|
|
update_post_meta($attach_id, 'image_hash', $image_hash);
|
|
|
|
// Retrieve the URL of the newly created attachment
|
|
$image_url = wp_get_attachment_url($attach_id);
|
|
|
|
// Return a successful response with the image URL
|
|
return new WP_REST_Response(
|
|
array('url' => $image_url),
|
|
200
|
|
);
|
|
}
|
|
|
|
|
|
private function get_attachment_by_hash($hash) {
|
|
$args = array(
|
|
'post_type' => 'attachment',
|
|
'post_status' => 'inherit',
|
|
'posts_per_page' => 1,
|
|
'meta_query' => array(
|
|
array(
|
|
'key' => 'image_hash',
|
|
'value' => $hash,
|
|
'compare' => '='
|
|
)
|
|
)
|
|
);
|
|
|
|
$query = new WP_Query($args);
|
|
|
|
if ($query->have_posts()) {
|
|
return $query->posts[0];
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public function scrobble($request) {
|
|
global $wpdb;
|
|
$data = $request->get_json_params();
|
|
|
|
// Updated required fields: 'album_name' is no longer required
|
|
$required_fields = ['song_name', 'author'];
|
|
|
|
// Check for missing required fields
|
|
foreach ($required_fields as $field) {
|
|
if (!isset($data[$field])) {
|
|
return new WP_Error('missing_field', 'Missing required field: ' . $field, array('status' => 400));
|
|
}
|
|
}
|
|
|
|
$table_name = 'song_scrobbles';
|
|
$cover_url = isset($data['cover_url']) ? $data['cover_url'] : null;
|
|
$album_name = isset($data['album_name']) ? $data['album_name'] : null;
|
|
|
|
// If 'album_name' is not provided, 'cover_url' must be present
|
|
if (empty($album_name)) {
|
|
if (empty($cover_url)) {
|
|
return new WP_Error(
|
|
'missing_cover_url',
|
|
'Cover URL must be provided if album name is not present',
|
|
array('status' => 400)
|
|
);
|
|
}
|
|
} else {
|
|
// If 'album_name' is provided but 'cover_url' is not, attempt to retrieve it from existing entries
|
|
if (empty($cover_url)) {
|
|
// Prepare case-insensitive search
|
|
$song_name_lower = strtolower($data['song_name']);
|
|
$album_name_lower = strtolower($album_name);
|
|
$author_lower = strtolower($data['author']);
|
|
|
|
// Query to find the most recent matching entry
|
|
$query = $wpdb->prepare(
|
|
"SELECT cover_url FROM $table_name
|
|
WHERE LOWER(album_name) = %s AND LOWER(author) = %s
|
|
ORDER BY id DESC
|
|
LIMIT 1",
|
|
$album_name_lower, $author_lower
|
|
);
|
|
|
|
$cover_url = $wpdb->get_var($query);
|
|
|
|
// If no matching entry is found, return an error
|
|
if (!$cover_url) {
|
|
return new WP_Error(
|
|
'missing_cover_url',
|
|
'Cover URL not provided and no existing entry found for the given album and author',
|
|
array('status' => 400)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Insert the scrobble data into the database
|
|
$result = $wpdb->insert(
|
|
$table_name,
|
|
array(
|
|
'song_name' => $data['song_name'],
|
|
'album_name' => $album_name, // This can be null
|
|
'cover_url' => $cover_url,
|
|
'author' => $data['author'],
|
|
'length_seconds' => isset($data['length_seconds']) ? intval($data['length_seconds']) : null
|
|
),
|
|
array('%s', '%s', '%s', '%s', '%d')
|
|
);
|
|
|
|
// Handle potential database insertion errors
|
|
if ($result === false) {
|
|
return new WP_Error('db_error', 'Error saving scrobble', array('status' => 500));
|
|
}
|
|
|
|
// Return a successful response
|
|
return new WP_REST_Response(array('message' => 'Scrobble saved successfully'), 201);
|
|
}
|
|
|
|
|
|
public function add_admin_menu() {
|
|
add_options_page(
|
|
'Image Scrobble Settings',
|
|
'Image Scrobble',
|
|
'manage_options',
|
|
'image-scrobble-settings',
|
|
array($this, 'settings_page')
|
|
);
|
|
}
|
|
|
|
public function register_settings() {
|
|
register_setting('image_scrobble_settings', $this->option_name);
|
|
}
|
|
|
|
public function settings_page() {
|
|
?>
|
|
<div class="wrap">
|
|
<h1>Image Scrobble Settings</h1>
|
|
<form method="post" action="options.php">
|
|
<?php
|
|
settings_fields('image_scrobble_settings');
|
|
do_settings_sections('image_scrobble_settings');
|
|
?>
|
|
<table class="form-table">
|
|
<tr valign="top">
|
|
<th scope="row">AUTH_KEY</th>
|
|
<td>
|
|
<input type="text" name="<?php echo $this->option_name; ?>" value="<?php echo esc_attr(get_option($this->option_name)); ?>" />
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
<?php submit_button(); ?>
|
|
</form>
|
|
</div>
|
|
<?php
|
|
}
|
|
}
|
|
|
|
// Initialize the plugin
|
|
new ScrobbleHandler();
|