Bookracy Redirect

Adds a button to book-related websites to search the current book title on Bookracy.ru

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Bookracy Redirect
// @namespace    Violentmonkey Scripts
// @version      0.1
// @description  Adds a button to book-related websites to search the current book title on Bookracy.ru
// @author       Gemini
// @match        https://thegreatestbooks.org/*
// @match        https://www.goodreads.com/*
// @match        https://www.amazon.com/*
// @match        https://www.amazon.fr/*
// @match        https://www.amazon.de/*
// @match        https://www.amazon.co.uk/*
// @match        https://www.amazon.it/*
// @match        https://www.amazon.*/*
// @grant        none
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    /**
     * Attempts to extract the book title from the current page based on its hostname.
     * It uses specific selectors for known sites and falls back to general H1 tags or document title.
     * @returns {string} The extracted book title, or an empty string if not found.
     */
    function getBookTitle() {
        let title = '';
        const hostname = window.location.hostname;

        // --- Specific rules for different websites ---
        if (hostname.includes('goodreads.com')) {
            // Goodreads: Book title is usually in an h1 with id 'bookTitle'
            const el = document.getElementById('bookTitle');
            if (el) {
                title = el.innerText.trim();
            }
        } else if (hostname.includes('amazon.')) {
            // Amazon (all domains): Book title is usually in an h1 with id 'productTitle' or 'bookTitle'
            const el = document.getElementById('productTitle') || document.getElementById('bookTitle');
            if (el) {
                title = el.innerText.trim();
            }
        } else if (
            hostname.includes('thegreatestbooks.org')
            // Removed: hostname.includes('fivebooks.com')
            // Removed: hostname.includes('mostrecommendedbooks.com')
            // Removed: hostname.includes('redditreads.com')
        ) {
            // General approach for other book list/review sites:
            // Try common header tags for the main title on the page.
            // Prioritize a specific class if known, then general h1.
            let el = document.querySelector('h1.book-title') || document.querySelector('h1');
            if (el) {
                title = el.innerText.trim();
            }
            // Fallback to title tag if h1 not found or empty
            if (!title && document.title) {
                title = document.title;
            }
        }

        // --- General Fallback and Cleaning ---
        // If no specific rule matched or element found, use the document title as a last resort.
        if (!title && document.title) {
            title = document.title;
        }

        // Clean up common suffixes/prefixes often found in titles (e.g., from browser tabs or Goodreads)
        title = title
            .replace(/ - Wikipedia$/, '') // Remove Wikipedia suffix
            .replace(/ \| Goodreads$/, '') // Remove Goodreads suffix
            .replace(/ \| Five Books$/, '') // Remove Five Books suffix
            .replace(/\(Paperback\)/, '') // Remove (Paperback)
            .replace(/\(Hardcover\)/, '') // Remove (Hardcover)
            .replace(/\(Kindle\)/, '') // Remove (Kindle)
            .replace(/ by [A-Za-z\s]+$/, '') // Remove " by Author Name" at the end
            .replace(/ Series$/, '') // Remove " Series"
            .trim(); // Trim any leading/trailing whitespace

        return title;
    }

    /**
     * Creates and appends the "Search on Bookracy" button to the page.
     * The button will be positioned at the bottom right corner of the viewport.
     */
    function createBookracyButton() {
        const bookTitle = getBookTitle();

        // Only create the button if a book title was successfully extracted
        if (!bookTitle) {
            console.log("Book title not found on this page, skipping Bookracy button creation.");
            return;
        }

        const button = document.createElement('button');
        button.innerText = 'Search on Bookracy';

        // Apply basic inline styles for visibility and consistent appearance
        button.style.cssText = `
            position: fixed;
            bottom: 20px;
            right: 20px;
            background-color: #4CAF50; /* Green */
            color: white;
            padding: 10px 18px; /* Slightly more padding for touch targets */
            border: none;
            border-radius: 8px; /* Rounded corners */
            cursor: pointer;
            font-family: 'Inter', sans-serif; /* Use Inter font for consistency */
            font-size: 16px;
            font-weight: 500;
            z-index: 10000; /* Ensure button is above other content */
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25); /* Stronger shadow for depth */
            transition: background-color 0.3s ease, transform 0.2s ease, box-shadow 0.3s ease;
            outline: none; /* Remove focus outline */
        `;

        // Add hover effects for a more interactive feel
        button.onmouseover = function() {
            this.style.backgroundColor = '#45a049'; // Darker green on hover
            this.style.transform = 'scale(1.05)'; // Slightly enlarge on hover
            this.style.boxShadow = '0 6px 15px rgba(0, 0, 0, 0.3)'; // Enhanced shadow
        };

        // Revert styles on mouse out
        button.onmouseout = function() {
            this.style.backgroundColor = '#4CAF50';
            this.style.transform = 'scale(1)';
            this.style.boxShadow = '0 4px 12px rgba(0, 0, 0, 0.25)';
        };

        // Handle button click event
        button.onclick = function() {
            // Encode the book title to ensure it's a valid URL parameter
            const encodedTitle = encodeURIComponent(bookTitle);
            // Construct the Bookracy URL and open it in a new tab
            window.open(`https://bookracy.ru/?q=${encodedTitle}`, '_blank');
        };

        // Append the button to the document body
        document.body.appendChild(button);
    }

    // Ensure the script runs after the DOM is fully loaded.
    // This prevents errors if elements are not yet available.
    if (document.readyState === 'loading') {
        window.addEventListener('DOMContentLoaded', createBookracyButton);
    } else {
        // If the DOM is already loaded (e.g., script injected late), run immediately.
        createBookracyButton();
    }
})();