Greasy Fork

Kemono Discord Favourite Button

Add a favourite button to Discord server creator pages on Kemono

目前为 2025-04-17 提交的版本。查看 最新版本

// ==UserScript==
// @name         Kemono Discord Favourite Button
// @namespace    https://kemono.su/
// @author       Agent 9
// @version      1.0
// @license MIT
// @description  Add a favourite button to Discord server creator pages on Kemono
// @match        https://kemono.su/*
// @grant        window.onurlchange
// @run-at       document-end
// ==/UserScript==

(function () {
    // ————————————————————————
    // SPA Navigation Listener
    // ————————————————————————

    window.addEventListener('urlchange', () => {
        waitForElement('#main ul', (ul) => {
            initFavoriteButton();
        });
        console.log('Location changed');
    });
    window.addEventListener('load', () => {
        initFavoriteButton();
        console.log('load');
    });

    // ————————————————————————
    // Utilities
    // ————————————————————————
    function waitForElement(selector, callback) {
        const el = document.querySelector(selector);
        if (el) return callback(el);
        setTimeout(() => waitForElement(selector, callback), 100);
    }

    function getServerId(url) {
        const parts = url.split("/"); // splits into parts by "/"
        const serverIndex = parts.indexOf("server"); // find "server"
        return serverIndex !== -1 ? parts[serverIndex + 1].trim() : null;
    }


    // ————————————————————————
    // Main Injector / Syncer
    // ————————————————————————
    function initFavoriteButton() {
        // Only target Discord creator pages
        if (!/\/discord\//.test(location.pathname)) return;

        // Prevent duplicate injection
        if (document.getElementById('creator-actions')) return;

        // Create the favorite button
        const btn = document.createElement('button');
        btn.id = 'favorite-button-template';
        btn.className = 'user-header__favourite';
        btn.type = 'button';
        btn.innerHTML = `<span class="user-header__fav-icon">☆</span>
                         <span class="user-header__fav-text">Favorite</span>`;

        const service = 'discord';
        const profileID = getServerId(location.pathname);

        // Set initial state based on current favorites
        fetch('/api/v1/account/favorites', {
            method: 'GET',
            credentials: 'include'
        })
            .then(function(response){
            return response.json();
        })
            .then(function(data){
            const isFav = data.some(item => item.service == service && item.id == profileID);
            console.log(isFav);
            if(isFav==true){
                btn.className = 'user-header__favourite user-header__favourite--unfav ';
                btn.innerHTML =`<span class="user-header__fav-icon">★</span>
                                <span class="user-header__fav-text">Unfavorite</span>`;
            }
        })
            .catch(error => console.error('Error:', error));

        // Toggle favourite on click
        btn.addEventListener('click', () => {
            const isNowFav = btn.classList.toggle('user-header__favourite--unfav');
            if(isNowFav){
                btn.innerHTML =`<span class="user-header__fav-icon">★</span>
                                <span class="user-header__fav-text">Unfavorite</span>`;
            }
            else{
                btn.innerHTML = `<span class="user-header__fav-icon">☆</span>
                                 <span class="user-header__fav-text">Favorite</span>`;
            }
            const method = isNowFav ? 'POST' : 'DELETE';

            fetch(`/api/v1/favorites/creator/${service}/${profileID}`, {
                method,
                credentials: 'include',
            }).catch(console.error);
        });

        // Inject into page when element is ready
        waitForElement('#main ul', (ul) => {
            const container = document.createElement('div');
            container.id = 'creator-actions';
            container.appendChild(btn);
            ul.prepend(container);
        });
    }
})();