Discord/Shapes Tools

Various Functions for Shapes.inc for Discord

目前為 2024-11-29 提交的版本,檢視 最新版本

// ==UserScript==
// @name         Discord/Shapes Tools
// @namespace    https://vishanka.com
// @version      1.4
// @description  Various Functions for Shapes.inc for Discord
// @author       Vishanka
// @match        https://discord.com/channels/*
// @grant        GM_addStyle
// @grant        GM_xmlhttpRequest
// @license      Proprietary
// @run-at document-idle
// ==/UserScript==


(function() {
    'use strict';
let notifierActive = false;

// ================================================================== LOREBOOK ==================================================================
function LorebookScript(){

// Create and add the arrow button to open the storage panel
const arrowButton = document.createElement('div');
arrowButton.innerHTML = '〈';
arrowButton.style.position = 'fixed';
arrowButton.style.bottom = '50%';
arrowButton.style.right = '0';
arrowButton.style.padding = '10px';
arrowButton.style.fontSize = '24px';
arrowButton.style.zIndex = '1000';
arrowButton.style.cursor = 'pointer';
arrowButton.style.color = '#B4B4B4';
arrowButton.style.borderRadius = '5px 0 0 5px';
arrowButton.style.transition = 'transform 0.3s ease, right 0.3s ease, background-color 0.1s';

// Toggle panel visibility
arrowButton.addEventListener('click', () => {
  if (DCstoragePanel.style.right === '-250px') {
    DCstoragePanel.style.right = '0';
    arrowButton.style.right = '250px';
    arrowButton.style.transform = 'rotate(180deg)';
  } else {
    DCstoragePanel.style.right = '-250px';
    arrowButton.style.right = '0';
    arrowButton.style.transform = 'rotate(0deg)';
  }
});

// Create the fancy sliding panel
window.DCstoragePanel = document.createElement('div');
DCstoragePanel.style.position = 'fixed';
DCstoragePanel.style.top = '0';
DCstoragePanel.style.right = '-250px'; // Initially hidden
DCstoragePanel.style.height = '100%';
DCstoragePanel.style.width = '250px';
DCstoragePanel.style.backgroundColor = '#171717';
DCstoragePanel.style.transition = 'right 0.3s ease';
DCstoragePanel.style.zIndex = '999';

// Create the header above the button
const storagePanelHeader = document.createElement('div');
storagePanelHeader.innerText = 'Shapes Tools';
storagePanelHeader.style.margin = '20px';
storagePanelHeader.style.padding = '10px';
storagePanelHeader.style.fontSize = '19px';
storagePanelHeader.style.fontWeight = '550';
storagePanelHeader.style.color = '#ECECEC';
storagePanelHeader.style.textAlign = 'center';

// Create a divider line
const dividerLine = document.createElement('div');
dividerLine.style.height = '1px';
dividerLine.style.backgroundColor = '#212121';
dividerLine.style.margin = '10px 20px';

// Manage Lorebook Button
window.openLorebookButton = document.createElement('div');
window.openLorebookButton.innerHTML = `
    <button id="toggle-lorebook-panel"
        style="
            display: flex;
            align-items: center;
            gap: 8px;
            position: relative;
            top: 10px;
            right: 0px;
            left: 10px;
            padding: 7px 15px;
            background: transparent;
            color: #b0b0b0;
            border: none;
            border-radius: 8px;
            font-size: 16px;
            text-align: left;
            cursor: pointer;
            width: 90%;
            transition: background-color 0.1s, color 0.1s;
            z-index: 1001;">
        <svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg" class="mb-[-1px]">
            <path d="M6 3C4.89543 3 4 3.89543 4 5V13C4 14.1046 4.89543 15 6 15L6 3Z" fill="currentColor"></path>
            <path d="M7 3V15H8.18037L8.4899 13.4523C8.54798 13.1619 8.69071 12.8952 8.90012 12.6858L12.2931 9.29289C12.7644 8.82153 13.3822 8.58583 14 8.58578V3.5C14 3.22386 13.7761 3 13.5 3H7Z" fill="currentColor"></path>
            <path d="M11.3512 15.5297L9.73505 15.8529C9.38519 15.9229 9.07673 15.6144 9.14671 15.2646L9.46993 13.6484C9.48929 13.5517 9.53687 13.4628 9.60667 13.393L12.9996 10C13.5519 9.44771 14.4473 9.44771 14.9996 10C15.5519 10.5523 15.5519 11.4477 14.9996 12L11.6067 15.393C11.5369 15.4628 11.448 15.5103 11.3512 15.5297Z" fill="currentColor"></path>
        </svg>
        Manage Lorebook
    </button>
`;

const lorebookButtonElement = openLorebookButton.querySelector('button');
lorebookButtonElement.onmouseover = () => {
    lorebookButtonElement.style.backgroundColor = '#212121';
    lorebookButtonElement.style.color = '#ffffff';
};
lorebookButtonElement.onmouseout = () => {
    lorebookButtonElement.style.backgroundColor = 'transparent';
    lorebookButtonElement.style.color = '#b0b0b0';
};

// Create the main panel container
const lorebookPanel = document.createElement('div');
lorebookPanel.id = 'lorebookManagerPanel';
lorebookPanel.style.position = 'fixed';
lorebookPanel.style.top = '50%';
lorebookPanel.style.left = '50%';
lorebookPanel.style.transform = 'translate(-50%, -50%)';
// Size different for Mobile and Desktop
if (window.innerWidth <= 768) {
    lorebookPanel.style.width = '90%';
    lorebookPanel.style.height = '90%';
} else {
    lorebookPanel.style.width = '800px';
    lorebookPanel.style.height = '700px';
}
lorebookPanel.style.backgroundColor = '#2F2F2F';
lorebookPanel.style.borderRadius = '20px';
lorebookPanel.style.padding = '10px';
lorebookPanel.style.display = 'none';
lorebookPanel.style.zIndex = '1000';

// Add close button for the panel
const closeButton = document.createElement('button');
closeButton.innerText = '✕';
closeButton.style.position = 'absolute';
closeButton.style.borderRadius = '50%';
closeButton.style.color = '#ffffff';
closeButton.style.top = '20px';
closeButton.style.right = '20px';
closeButton.style.backgroundColor = 'transparent';
closeButton.style.cursor = 'pointer';

closeButton.addEventListener('mouseenter', () => {
    closeButton.style.backgroundColor = '#676767';
});
closeButton.addEventListener('mouseleave', () => {
    closeButton.style.backgroundColor = 'transparent';
});

// Hide the Lorebook Panel
closeButton.addEventListener('click', () => {
    lorebookPanel.style.display = 'none';
});

// Open the Lorebook Panel
openLorebookButton.addEventListener('click', () => {
    lorebookPanel.style.display = lorebookPanel.style.display === 'none' ? 'block' : 'none';
    loadProfileEntries();
});

// Profiles Title
const profileslabel = document.createElement('div');
profileslabel.textContent = 'Profiles';
profileslabel.style.color = '#dddddd';
profileslabel.style.fontSize = '14px';
profileslabel.style.marginBottom = '5px';
profileslabel.style.marginLeft = '3px';
profileslabel.style.marginTop = '5px';
profileslabel.style.fontSize = '20px';
profileslabel.style.fontWeight = '550';

// Profile Management Panel
const lorebookProfilePanel = document.createElement('div');
lorebookProfilePanel.id = 'lorebookProfilePanel';
lorebookProfilePanel.style.float = 'left';
lorebookProfilePanel.style.width = '20%';
lorebookProfilePanel.style.borderRight = '0.5px solid #444444';
lorebookProfilePanel.style.height = '93%';

// Create the profile list container
const profileList = document.createElement('div');
profileList.id = 'profileList';
profileList.style.height = '95%';
profileList.style.color = 'white';
profileList.style.overflowY = 'auto';

// Add Profiles Button
const addProfileButton = document.createElement('button');
addProfileButton.innerText = 'Add Profile';
addProfileButton.style.padding = '8px';
addProfileButton.style.border = '0.2px solid #4E4E4E';
addProfileButton.style.backgroundColor = 'transparent';
addProfileButton.style.color = '#fff';
addProfileButton.style.borderRadius = '20px';
addProfileButton.style.width = '90%';
addProfileButton.style.cursor = 'pointer';

// Mouseover Effect for Add Profiles Button
addProfileButton.onmouseover = () => {
    addProfileButton.style.backgroundColor = '#424242';
};
addProfileButton.onmouseout = () => {
    addProfileButton.style.backgroundColor = 'transparent';
};

addProfileButton.addEventListener('click', () => {
    const profileName = prompt('Enter profile name:');
    if (profileName) {
        const profileKey = `lorebook.profile:${profileName}`;

        // Create a list of keys from localStorage that match the prefix 'lorebook.profile:'
        const existingKeys = Object.keys(localStorage)
            .filter(key => key.startsWith('lorebook.profile:'))
            .map(key => key.toLowerCase()); // Convert all keys to lowercase for case-insensitive check

        if (!existingKeys.includes(profileKey.toLowerCase())) {
            localStorage.setItem(profileKey, JSON.stringify({}));
            loadProfiles();
        } else {
            alert('Profile already exists.');
        }
    }
});


// Profile Selection Functionality
function loadProfiles() {
    profileList.innerHTML = '';
        Object.keys(localStorage).forEach(profileKey => {
            if (profileKey.startsWith('lorebook.profile:')) {
                const profileName = profileKey.replace('lorebook.profile:', '');
                const profileItem = document.createElement('div');
                profileItem.innerText = profileName;
                profileItem.style.padding = '5px';
                profileItem.style.marginBottom = '5px';
                profileItem.style.cursor = 'pointer';
                profileItem.style.backgroundColor = profileName === getCurrentProfile() ? '#424242' : '#2F2F2F';
                profileItem.style.borderRadius = '5px';
                profileItem.style.width = '90%';
                profileItem.style.position = 'relative';

                profileItem.addEventListener('click', () => {
                    setCurrentProfile(profileName);
                    loadProfiles();
                    loadProfileEntries();
                });

                const removeButton = document.createElement('button');
                removeButton.innerText = '✕';
                removeButton.style.position = 'absolute';
                removeButton.style.top = '3px';
                removeButton.style.right = '10px';
                removeButton.style.cursor = 'pointer';
                removeButton.style.backgroundColor = 'transparent';
                removeButton.style.color = 'white';
                removeButton.addEventListener('click', (e) => {
                    e.stopPropagation();
                    localStorage.removeItem(profileKey);
                    if (profileName === getCurrentProfile()) {
                        setCurrentProfile(null);
                    }
                    loadProfiles();
                    loadProfileEntries();
                });

                profileItem.appendChild(removeButton);
                profileList.appendChild(profileItem);
            }
        });
}

// Lorebook Entries Title
const lorebookEntriesTitle = document.createElement('h3');
lorebookEntriesTitle.innerText = 'Manage Lorebook Entries';
lorebookEntriesTitle.style.fontWeight = 'normal';
lorebookEntriesTitle.style.color = '#ffffff';
lorebookEntriesTitle.style.textAlign = 'left';
lorebookEntriesTitle.style.fontSize = '24px';
lorebookEntriesTitle.style.marginTop = '20px';
lorebookEntriesTitle.style.position = 'relative';
lorebookEntriesTitle.style.marginLeft = '23%';
lorebookEntriesTitle.style.marginBottom = '15px';
lorebookEntriesTitle.style.fontWeight = '550';

// Profile Entries List
const profileEntriesList = document.createElement('div');
profileEntriesList.id = 'profileEntriesList';
profileEntriesList.style.marginTop = '20px';
profileEntriesList.style.height = '48%';
// Check if the device is mobile
if (window.innerWidth <= 768) {
    profileEntriesList.style.height = '30%';
} else {
    profileEntriesList.style.height = '48%';
}
profileEntriesList.style.overflowY = 'auto';

// Header for Inputs
const entrieslabel = document.createElement('div');
entrieslabel.textContent = 'Enter keys and description:';
entrieslabel.style.color = '#dddddd';
entrieslabel.style.fontSize = '14px';
entrieslabel.style.marginBottom = '5px';
entrieslabel.style.marginTop = '5px';
entrieslabel.style.marginLeft = '23%';

// Create key-value input fields
const inputContainer = document.createElement('div');
inputContainer.id = 'inputContainer';
inputContainer.style.marginTop = '10px';
inputContainer.style.display = 'flex';
inputContainer.style.flexDirection = 'column';
inputContainer.style.alignItems = 'center';
inputContainer.style.margin = '0 auto';


const lorebookKeyInput = document.createElement('input');
lorebookKeyInput.type = 'text';
lorebookKeyInput.placeholder = 'Entry Keywords (comma-separated)';
lorebookKeyInput.style.width = '90%';
lorebookKeyInput.style.marginBottom = '5px';
lorebookKeyInput.style.padding = '10px';
lorebookKeyInput.style.border = '1px solid #444444';
lorebookKeyInput.style.borderRadius = '8px';
lorebookKeyInput.style.backgroundColor = '#1e1e1e';
lorebookKeyInput.style.color = '#dddddd';


const lorebookValueInput = document.createElement('textarea');
lorebookValueInput.placeholder = ' ';
lorebookValueInput.style.width = '90%';
lorebookValueInput.style.marginBottom = '5px';
lorebookValueInput.style.padding = '10px';
lorebookValueInput.style.border = '1px solid #444444';
lorebookValueInput.style.borderRadius = '8px';
lorebookValueInput.style.backgroundColor = '#1e1e1e';
lorebookValueInput.style.color = '#dddddd';
lorebookValueInput.style.height = '100px';
lorebookValueInput.style.resize = 'vertical';
lorebookValueInput.maxLength = 1000;
lorebookValueInput.style.overflow = 'auto';

const charCounter = document.createElement('div');
charCounter.style.color = '#dddddd';
charCounter.style.fontSize = '12px';
charCounter.style.marginTop = '0px';
charCounter.style.marginBottom = '15px';
charCounter.style.textAlign = 'right';
charCounter.style.marginRight = '-87%';
charCounter.style.color = 'grey';
charCounter.textContent = `0/${lorebookValueInput.maxLength}`;

// Update the counter as the user types
lorebookValueInput.addEventListener('input', () => {
  charCounter.textContent = `${lorebookValueInput.value.length}/${lorebookValueInput.maxLength}`;
});

// Save Entry button, also important for editing
const lorebookSaveButton = document.createElement('button');
lorebookSaveButton.innerText = 'Add Entry';
lorebookSaveButton.style.padding = '10px 20px';
lorebookSaveButton.style.border = '0.2px solid #4E4E4E';
lorebookSaveButton.style.backgroundColor = '#2F2F2F';
lorebookSaveButton.style.color = '#fff';
lorebookSaveButton.style.borderRadius = '50px';
lorebookSaveButton.style.cursor = 'pointer';
lorebookSaveButton.style.width = '95%';

// Append all Elements
document.body.appendChild(arrowButton);
document.body.appendChild(DCstoragePanel);
DCstoragePanel.appendChild(storagePanelHeader);
DCstoragePanel.appendChild(dividerLine);
document.body.appendChild(lorebookPanel);
lorebookPanel.appendChild(closeButton);
lorebookPanel.appendChild(profileslabel);
lorebookPanel.appendChild(lorebookProfilePanel);
lorebookProfilePanel.appendChild(profileList);
lorebookProfilePanel.appendChild(addProfileButton);
lorebookPanel.appendChild(lorebookEntriesTitle);
lorebookPanel.appendChild(profileEntriesList);
lorebookPanel.appendChild(entrieslabel);
lorebookPanel.appendChild(inputContainer);
inputContainer.appendChild(lorebookKeyInput);
inputContainer.appendChild(lorebookValueInput);
inputContainer.appendChild(charCounter);
inputContainer.appendChild(lorebookSaveButton);

let isEditing = false;
let editingKey = '';

lorebookSaveButton.addEventListener('click', () => {
    const key = lorebookKeyInput.value.trim().toLowerCase(); // Ensure key is always saved as lowercase
    const value = lorebookValueInput.value;
    const currentProfile = getCurrentProfile();

    if (key && currentProfile) {
        const profileKey = `${currentProfile}.lorebook:${key}`;
        const formattedValue = `<[Lorebook: ${key}] ${value}>`;

        // Check for duplicate keys (case-insensitive) and prevent keys that partially match an existing key
        const isDuplicateKey = Object.keys(localStorage).some(storageKey => {
            const normalizedStorageKey = storageKey.toLowerCase();
            const normalizedCurrentProfile = currentProfile.toLowerCase();
            const currentKey = normalizedStorageKey.replace(`${normalizedCurrentProfile}.lorebook:`.toLowerCase(), '');
            return (
                (currentKey === key || currentKey.split(',').includes(key)) &&
                (!isEditing || editingKey.toLowerCase() !== currentKey)
            );
        });

        // Enforce uniqueness for edits as well
        if (isDuplicateKey) {
            alert('The key is already used in an existing entry (case-insensitive). Please use a different key.');
            return;
        }

        // Remove the old key if editing and key has changed
        if (isEditing && editingKey.toLowerCase() !== key) {
            const oldProfileKey = `${currentProfile}.lorebook:${editingKey.toLowerCase()}`;
            localStorage.removeItem(oldProfileKey);
        }

        localStorage.setItem(profileKey, formattedValue);
        lorebookKeyInput.value = '';
        lorebookValueInput.value = '';
        isEditing = false;
        editingKey = '';
        loadProfileEntries();
    } else {
        alert('Please select a profile and enter a key.');
    }
});



function loadProfileEntries() {
    profileEntriesList.innerHTML = '';
    profileEntriesList.style.display = 'flex';
    profileEntriesList.style.flexDirection = 'column';
    profileEntriesList.style.alignItems = 'center';
    profileEntriesList.style.margin = '0 auto';

    const currentProfile = getCurrentProfile();
    if (currentProfile) {
        Object.keys(localStorage).forEach(storageKey => {
            // Normalize both the profile and the storage key for case-insensitive comparison
            if (storageKey.toLowerCase().startsWith(`${currentProfile.toLowerCase()}.lorebook:`)) {
                const entryKey = storageKey.replace(new RegExp(`^${currentProfile}\.lorebook:`, 'i'), '');
                const entryValue = localStorage.getItem(storageKey);
                const displayedValue = entryValue.replace(/^<\[Lorebook:.*?\]\s*/, '').replace(/>$/, '');

                const entryItem = document.createElement('div');
                entryItem.style.padding = '10px';
                entryItem.style.marginBottom = '12px';
                entryItem.style.borderRadius = '8px';
                entryItem.style.backgroundColor = '#424242';
                entryItem.style.position = 'relative';
                entryItem.style.color = 'white';
                entryItem.style.flexDirection = 'column';
                entryItem.style.width = '90%';

                const keyElement = document.createElement('div');
                keyElement.innerText = entryKey;
                keyElement.style.fontWeight = 'bold';
                keyElement.style.marginBottom = '10px';
                entryItem.appendChild(keyElement);

                const valueElement = document.createElement('div');
                valueElement.innerText = displayedValue;
                entryItem.appendChild(valueElement);

                entryItem.addEventListener('click', () => {
                    lorebookKeyInput.value = entryKey;
                    lorebookValueInput.value = entryValue.replace(/^<\[Lorebook:.*?\]\s*/, '').replace(/>$/, '');
                    isEditing = true;
                    editingKey = entryKey;
                });

                const removeButton = document.createElement('button');
                removeButton.innerText = '✕';
                removeButton.style.position = 'absolute';
                removeButton.style.top = '10px';
                removeButton.style.right = '10px';
                removeButton.style.cursor = 'pointer';
                removeButton.style.backgroundColor = 'transparent';
                removeButton.style.color = 'white';
                removeButton.addEventListener('click', (event) => {
                    event.stopPropagation();
                    localStorage.removeItem(storageKey);
                    loadProfileEntries();
                });

                entryItem.appendChild(removeButton);
                profileEntriesList.appendChild(entryItem);
            }
        });
    }
}

// Utility functions to manage profiles and local storage
function getCurrentProfile() {
    // Return the current profile name in its original case, but convert to lower case for comparisons
    const selectedProfile = localStorage.getItem('selectedProfile.lorebook');
    return selectedProfile ? selectedProfile : null;
}

function setCurrentProfile(profileName) {
    localStorage.setItem('selectedProfile.lorebook', profileName);
}

loadProfiles();

}

// ================================================================ IMPORT/EXPORT ===============================================================
function ImportExportScript() {
// Create buttons to trigger export and import
window.exportButton = document.createElement('div');
exportButton.innerHTML = `
    <button id="toggle-export-button"
        style="
            position: relative;
            top: 10px;
            right: 0px;
            left: 10px;
            padding: 7px 15px;
            background: transparent;
            color: #b0b0b0;
            border: none;
            border-radius: 8px;
            font-size: 16px;
            text-align: left;
            cursor: pointer;
            width: 90%;
            transition: background-color 0.1s, color 0.1s;
            z-index: 1001;
            display: flex;
            align-items: center;">
        <svg width="20px" height="20px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" style="margin-right: 8px;">
            <path d="M12 5L11.2929 4.29289L12 3.58579L12.7071 4.29289L12 5ZM13 14C13 14.5523 12.5523 15 12 15C11.4477 15 11 14.5523 11 14L13 14ZM6.29289 9.29289L11.2929 4.29289L12.7071 5.70711L7.70711 10.7071L6.29289 9.29289ZM12.7071 4.29289L17.7071 9.29289L16.2929 10.7071L11.2929 5.70711L12.7071 4.29289ZM13 5L13 14L11 14L11 5L13 5Z" fill="#B0B0B0"></path>
            <path d="M5 16L5 17C5 18.1046 5.89543 19 7 19L17 19C18.1046 19 19 18.1046 19 17V16" stroke="#B0B0B0" stroke-width="2"></path>
        </svg>
        Export Data
    </button>
`;


window.exportButton.onmouseover = () => {
  exportButton.querySelector('button').style.backgroundColor = '#212121';
  exportButton.querySelector('button').style.color = '#ffffff';
};
exportButton.onmouseout = () => {
  exportButton.querySelector('button').style.backgroundColor = 'transparent';
  exportButton.querySelector('button').style.color = '#b0b0b0';
};
//DCstoragePanel.appendChild(exportButton);

window.importButton = document.createElement('div');
importButton.innerHTML = `
    <button id="toggle-import-button"
        style="
            position: relative;
            top: 10px;
            right: 0px;
            left: 10px;
            padding: 7px 15px;
            background: transparent;
            color: #b0b0b0;
            border: none;
            border-radius: 8px;
            font-size: 16px;
            text-align: left;
            cursor: pointer;
            width: 90%;
            transition: background-color 0.1s, color 0.1s;
            z-index: 1001;
            display: flex;
            align-items: center;
            gap: 8px;">
        <svg width="20px" height="20px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
            <path d="M12 14L11.2929 14.7071L12 15.4142L12.7071 14.7071L12 14ZM13 5C13 4.44772 12.5523 4 12 4C11.4477 4 11 4.44771 11 5L13 5ZM6.29289 9.70711L11.2929 14.7071L12.7071 13.2929L7.70711 8.29289L6.29289 9.70711ZM12.7071 14.7071L17.7071 9.70711L16.2929 8.29289L11.2929 13.2929L12.7071 14.7071ZM13 14L13 5L11 5L11 14L13 14Z" fill="#B0B0B0"></path>
            <path d="M5 16L5 17C5 18.1046 5.89543 19 7 19L17 19C18.1046 19 19 18.1046 19 17V16" stroke="#B0B0B0" stroke-width="2"></path>
        </svg>
        Import Data
    </button>
`;

importButton.onmouseover = () => {
  importButton.querySelector('button').style.backgroundColor = '#212121';
  importButton.querySelector('button').style.color = '#ffffff';
};
importButton.onmouseout = () => {
  importButton.querySelector('button').style.backgroundColor = 'transparent';
  importButton.querySelector('button').style.color = '#b0b0b0';
};
//DCstoragePanel.appendChild(importButton);

    // Export specific localStorage entries
    exportButton.addEventListener('click', () => {
        const filteredData = {};
        for (const key in localStorage) {
            if (localStorage.hasOwnProperty(key)) {
                if (key.startsWith('events') || key.includes('lorebook') || key.includes('rules') || key.includes('notifier')) {
                    filteredData[key] = localStorage.getItem(key);
                }
            }
        }
        const data = JSON.stringify(filteredData);
        const blob = new Blob([data], {type: 'application/json'});
        const url = URL.createObjectURL(blob);

        const a = document.createElement('a');
        a.href = url;
        a.download = 'localStorage_filtered.json';
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
    });

    // Import localStorage
    importButton.addEventListener('click', () => {
        const input = document.createElement('input');
        input.type = 'file';
        input.accept = 'application/json';
        input.addEventListener('change', (event) => {
            const file = event.target.files[0];
            if (!file) {
                return;
            }

            const reader = new FileReader();
            reader.onload = (e) => {
                try {
                    const importedData = JSON.parse(e.target.result);
                    for (const key in importedData) {
                        localStorage.setItem(key, importedData[key]);
                    }
                    alert('localStorage has been successfully imported.');
                } catch (err) {
                    alert('Failed to import localStorage: ' + err.message);
                }
            };
            reader.readAsText(file);
        });
        input.click();
    });
    }

// =================================================================== EVENTS ===================================================================
function EventsScript() {

window.eventsButton = document.createElement('div');
window.eventsButton.innerHTML = `
    <button id="toggle-events-panel"
        style="
            position: relative;
            top: 10px;
            right: 0px;
            left: 10px;
            padding: 7px 15px;
            display: flex;
            align-items: center;

            text-align: left;
            background: transparent;
            color: #b0b0b0;
            border: none;
            border-radius: 8px;
            font-size: 16px;
            cursor: pointer;
            width: 90%;
            transition: background-color 0.1s, color 0.1s;
            z-index: 1001;">
<svg fill="#B0B0B0" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24" xml:space="preserve" width="20px" height="20px" style="padding-right: 5px; margin-left: 1px;">

            <g id="SVGRepo_bgCarrier" stroke-width="0"></g>
            <g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g>
            <g id="SVGRepo_iconCarrier">
                <path d="M5,2v2H4C2.9,4,2,4.9,2,6v11c0,1.1,0.9,2,2,2h6.8c1.8-1.8,0,0,2-2H4V8h12v5.9c1.6-1.6,0.2-0.2,2-2V6c0-1.1-0.9-2-2-2h-1V2 h-2v2H7V2H5z M10,9.2l-0.8,2L7,11.4l1.6,1.4l-0.5,2.1l1.8-1.1l1.8,1.1l-0.5-2.1l1.6-1.4l-2.2-0.2L10,9.2z M20.5,12 c-0.1,0-0.3,0.1-0.4,0.2L19.3,13l2,2l0.8-0.8c0.2-0.2,0.2-0.6,0-0.7l-1.3-1.3C20.8,12,20.6,12,20.5,12z M18.8,13.5L12.3,20v2h2 l6.5-6.5L18.8,13.5"></path>
            </g>
        </svg>
        Manage Events
    </button>
`;


let manageEventsButton = window.eventsButton.querySelector('#toggle-events-panel');
manageEventsButton.onclick = openProfilePanel;

const eventsbuttonElement = eventsButton.querySelector('button');
eventsbuttonElement.onmouseover = () => {
    eventsbuttonElement.style.backgroundColor = '#212121';
    eventsbuttonElement.style.color = '#ffffff';
};
eventsbuttonElement.onmouseout = () => {
    eventsbuttonElement.style.backgroundColor = 'transparent';
    eventsbuttonElement.style.color = '#b0b0b0';
};

function openProfilePanel() {

    if (document.querySelector('#eventsProfilePanel')) {
        return;
    }

// Create profile management panel
const eventsProfilePanel = document.createElement('div');
eventsProfilePanel.id = 'eventsProfilePanel';
eventsProfilePanel.style.position = 'fixed';
eventsProfilePanel.style.top = '50%';
eventsProfilePanel.style.left = '50%';
eventsProfilePanel.style.transform = 'translate(-50%, -50%)';
// Size different for Mobile and Desktop
if (window.innerWidth <= 768) {
    eventsProfilePanel.style.width = '90%';
    eventsProfilePanel.style.height = '90%';
} else {
    eventsProfilePanel.style.width = '800px';
    eventsProfilePanel.style.height = '700px';
}
//eventsProfilePanel.style.width = '800px';
//eventsProfilePanel.style.height = '700px';
eventsProfilePanel.style.backgroundColor = '#2F2F2F';
eventsProfilePanel.style.color = 'white';
eventsProfilePanel.style.borderRadius = '20px';
eventsProfilePanel.style.padding = '20px';
eventsProfilePanel.style.zIndex = '1000';
eventsProfilePanel.style.display = 'flex';
eventsProfilePanel.style.flexDirection = 'row';

// Create close button for profilePanel
const closeButton = document.createElement('button');
closeButton.style.position = 'absolute';
closeButton.style.top = '15px';
closeButton.style.right = '15px';
closeButton.style.width = '30px';
closeButton.style.height = '30px';
closeButton.style.backgroundColor = 'transparent';
closeButton.style.color = '#ffffff';
closeButton.style.border = 'none';
closeButton.style.borderRadius = '50%';
closeButton.style.cursor = 'pointer';
closeButton.style.display = 'flex';
closeButton.style.alignItems = 'center';
closeButton.style.zIndex = '1001';
closeButton.style.justifyContent = 'center';
closeButton.style.transition = 'background-color 0.2s ease';
closeButton.style.boxSizing = 'border-box';

// Create span for the '✕' character
const closeIcon = document.createElement('span');
closeIcon.innerText = '✕';
closeIcon.style.fontSize = '16px';
closeIcon.style.position = 'relative';
closeIcon.style.top = '-1px';

// Hover effect
closeButton.addEventListener('mouseenter', () => {
    closeButton.style.backgroundColor = '#676767';
});

closeButton.addEventListener('mouseleave', () => {
    closeButton.style.backgroundColor = 'transparent';
});

// Close button action
closeButton.onclick = function() {
    document.body.removeChild(eventsProfilePanel);
};

// Create profile list container
const profileListContainer = document.createElement('div');
profileListContainer.style.flex = '0.50';
profileListContainer.style.marginRight = '20px';
profileListContainer.style.paddingRight = '20px';
profileListContainer.style.display = 'flex';
profileListContainer.style.flexDirection = 'column';
profileListContainer.style.borderRight = '1px solid #444444';
profileListContainer.style.overflowY = 'auto';
profileListContainer.style.maxHeight = '660px';

// Create header for profile list
const profileListHeader = document.createElement('h4');
profileListHeader.innerText = 'Profiles';
profileListHeader.style.marginBottom = '10px';

// Create profile list
const profileList = document.createElement('ul');
profileList.style.overflowY = 'auto';
profileList.style.height = '600px';


// Create button to add profile
const addProfileButton = document.createElement('button');
addProfileButton.innerText = 'Add Profile';
addProfileButton.style.padding = '8px';
addProfileButton.style.border = '0.2px solid #4E4E4E';

addProfileButton.style.backgroundColor = 'transparent';
addProfileButton.style.color = '#fff';
addProfileButton.style.borderRadius = '20px';
addProfileButton.style.cursor = 'pointer';

addProfileButton.onmouseover = () => {
    addProfileButton.style.backgroundColor = '#424242';
};
addProfileButton.onmouseout = () => {
    addProfileButton.style.backgroundColor = 'transparent';
};
addProfileButton.onclick = function() {
    openAddProfileDialog();
};

// Create key-value input container
const keyValueContainer = document.createElement('div');
keyValueContainer.style.flex = '2.3';
keyValueContainer.style.display = 'flex';
keyValueContainer.style.flexDirection = 'column';
keyValueContainer.style.gap = '10px';

// Create entries list
const entriesList = document.createElement('div');
entriesList.style.overflowY = 'auto';
entriesList.style.height = '340px';
entriesList.style.width = '100%';
entriesList.style.paddingRight = '20px';
entriesList.style.borderCollapse = 'collapse';
entriesList.style.display = 'block';
entriesList.style.overflowY = 'auto';

// Create a header above the headerRow
const manageEventsHeader = document.createElement('h2');
manageEventsHeader.innerText = 'Manage Event List';
manageEventsHeader.style.marginBottom = '-10px';

closeButton.appendChild(closeIcon);
eventsProfilePanel.appendChild(closeButton);
profileListContainer.appendChild(profileListHeader);
profileListContainer.appendChild(profileList);
profileListContainer.appendChild(addProfileButton);
keyValueContainer.appendChild(manageEventsHeader);

// Create table header
const headerRow = document.createElement('tr');
const headers = ['Key', 'Value', '%', 'Time', ''];
headers.forEach(headerText => {
    const header = document.createElement('th');
    header.innerText = headerText;
    header.style.padding = '5px';
    header.style.textAlign = 'left';
        if (headerText === 'Value') {
            header.style.width = '60%';
        } else if (headerText === 'Key') {
            header.style.width = '15%';
        } else if (headerText === '%' || headerText === 'Time') {
            header.style.width = '10%';
        } else if (headerText === '') {
            header.style.width = '5%';
        }
    headerRow.appendChild(header);
});

const headerContainer = document.createElement('div');
headerContainer.style.position = 'sticky';
headerContainer.style.top = '0';
headerContainer.style.backgroundColor = '#2F2F2F';
headerContainer.style.zIndex = '1';
headerContainer.appendChild(headerRow);
entriesList.appendChild(headerContainer);
entriesList.style.position = 'sticky';
entriesList.style.top = '0';
entriesList.style.backgroundColor = '#2F2F2F';
// Create a separate header for the entries list
const entriesHeaderContainer = document.createElement('div');
entriesHeaderContainer.style.position = 'sticky';
entriesHeaderContainer.style.top = '0';
entriesHeaderContainer.style.backgroundColor = '#2F2F2F';
entriesHeaderContainer.style.zIndex = '1';
const entriesHeader = document.createElement('div');
entriesHeader.style.display = 'flex';
entriesHeader.style.padding = '5px 0';
entriesHeader.style.borderBottom = '1px solid #444444';
headers.forEach(headerText => {
  const header = document.createElement('div');
  header.innerText = headerText;
  header.style.padding = '5px';
  header.style.textAlign = 'left'; // Align headers to the left
    if (headerText === 'Value') {
        header.style.width = '57%';
    } else if (headerText === 'Key') {
        header.style.width = '15%';
    } else if (headerText === '%' || headerText === 'Time') {
        header.style.width = '7%';
    } else if (headerText === '') {
        header.style.width = '5%';
    }
  entriesHeader.appendChild(header);
});
entriesHeaderContainer.appendChild(entriesHeader);
keyValueContainer.appendChild(entriesHeaderContainer);
keyValueContainer.appendChild(entriesList);

// Create container for probability and time range inputs
const probTimeContainer = document.createElement('div');
probTimeContainer.style.display = 'flex';
probTimeContainer.style.gap = '10px';
probTimeContainer.style.marginBottom = '-4px';

// Create probability label and input
const probabilityContainer = document.createElement('div');
probabilityContainer.style.display = 'flex';
probabilityContainer.style.flexDirection = 'column';
probabilityContainer.style.width = '30%'; // Adjust width to fit the row better

const probabilityLabel = document.createElement('div');
probabilityLabel.innerText = 'Event Probability';
probabilityLabel.style.color = 'white';
probabilityLabel.style.marginBottom = '0px';
probabilityContainer.appendChild(probabilityLabel);

const probabilityInputContainer = document.createElement('div');
probabilityInputContainer.style.display = 'flex';
probabilityInputContainer.style.alignItems = 'center';

const probabilityInput = document.createElement('input');
probabilityInput.type = 'number';
probabilityInput.placeholder = '0-100';
probabilityInput.style.backgroundColor = '#1E1E1E';
probabilityInput.style.color = 'white';
probabilityInput.style.border = '1px solid #444444';
probabilityInput.style.borderRadius = '5px';
probabilityInput.style.padding = '5px';
probabilityInput.style.width = '85%';
probabilityInput.style.marginRight = '5px';
probabilityInputContainer.appendChild(probabilityInput);

const probabilityPercentLabel = document.createElement('span');
probabilityPercentLabel.innerText = '%';
probabilityPercentLabel.style.color = 'white';
probabilityInputContainer.appendChild(probabilityPercentLabel);

probabilityContainer.appendChild(probabilityInputContainer);
probTimeContainer.appendChild(probabilityContainer);

// Create time range label and input
const timeRangeContainer = document.createElement('div');
timeRangeContainer.style.display = 'flex';
timeRangeContainer.style.flexDirection = 'column';
timeRangeContainer.style.width = '30%'; // Adjust width to fit the row better

const timeRangeLabel = document.createElement('div');
timeRangeLabel.innerText = 'Time Range';
timeRangeLabel.style.color = 'white';
timeRangeLabel.style.marginBottom = '0px';
timeRangeContainer.appendChild(timeRangeLabel);

const timeRangeInputContainer = document.createElement('div');
timeRangeInputContainer.style.display = 'flex';
timeRangeInputContainer.style.alignItems = 'center';

const timeRangeInput = document.createElement('input');
timeRangeInput.type = 'text';
timeRangeInput.placeholder = '0-24';
timeRangeInput.value = '0-24'; // Set default value

timeRangeInput.style.backgroundColor = '#1E1E1E';
timeRangeInput.style.color = 'white';
timeRangeInput.style.border = '1px solid #444444';
timeRangeInput.style.borderRadius = '5px';
timeRangeInput.style.padding = '5px';
timeRangeInput.style.width = '85%';
timeRangeInput.style.marginRight = '5px';

timeRangeInput.addEventListener('blur', () => {
    const timeValue = timeRangeInput.value.trim();
    const timeRegex = /^([0-9]|1[0-9]|2[0-3])-(?:[0-9]|1[0-9]|2[0-3])$/;
    if (!timeRegex.test(timeValue)) {
        alert('Please enter a valid time range between 0-23, e.g., "8-16" or "0-24". Defaulting to "0-24".');
        timeRangeInput.value = '0-24';
    }
});

timeRangeInputContainer.appendChild(timeRangeInput);

const timeRangeUnitLabel = document.createElement('span');
timeRangeUnitLabel.innerText = 'h';
timeRangeUnitLabel.style.color = 'white';
timeRangeInputContainer.appendChild(timeRangeUnitLabel);

timeRangeContainer.appendChild(timeRangeInputContainer);
probTimeContainer.appendChild(timeRangeContainer);

// Create overall probability label and input
const overallProbabilityContainer = document.createElement('div');
overallProbabilityContainer.style.display = 'flex';
overallProbabilityContainer.style.flexDirection = 'column';
overallProbabilityContainer.style.width = '30%'; // Adjust width to fit the row better

const overallProbabilityLabel = document.createElement('div');
overallProbabilityLabel.innerText = 'Overall Probability';
overallProbabilityLabel.style.color = 'white';
overallProbabilityLabel.style.marginBottom = '0px';
overallProbabilityContainer.appendChild(overallProbabilityLabel);

const overallProbabilityInputContainer = document.createElement('div');
overallProbabilityInputContainer.style.display = 'flex';
overallProbabilityInputContainer.style.alignItems = 'center';

const overallProbabilityInput = document.createElement('input');
overallProbabilityInput.type = 'number';
overallProbabilityInput.placeholder = '0-100';
overallProbabilityInput.style.backgroundColor = '#202530';
overallProbabilityInput.style.color = 'white';
overallProbabilityInput.style.border = '1px solid #444444';
overallProbabilityInput.style.borderRadius = '5px';
overallProbabilityInput.style.padding = '5px';
overallProbabilityInput.style.marginRight = '5px';
overallProbabilityInput.style.width = '85%';

// Load the existing overall probability value if set
const savedProbability = localStorage.getItem('events.probability');
if (savedProbability) {
    overallProbabilityInput.value = savedProbability;
}

// Add event listener to save the value to localStorage when changed
overallProbabilityInput.addEventListener('input', () => {
    const probabilityValue = overallProbabilityInput.value.trim();
    if (probabilityValue !== '' && probabilityValue >= 0 && probabilityValue <= 100) {
        localStorage.setItem('events.probability', probabilityValue);
    } else {
        alert('Please enter a valid probability between 0 and 100.');
    }
});

overallProbabilityInputContainer.appendChild(overallProbabilityInput);

const overallProbabilityPercentLabel = document.createElement('span');
overallProbabilityPercentLabel.innerText = '%';
overallProbabilityPercentLabel.style.color = 'white';
overallProbabilityInputContainer.appendChild(overallProbabilityPercentLabel);

overallProbabilityContainer.appendChild(overallProbabilityInputContainer);
probTimeContainer.appendChild(overallProbabilityContainer);

// Append probability and time range container to the main keyValue container
keyValueContainer.appendChild(probTimeContainer);

// Create input for key
const keyInput = document.createElement('input');
keyInput.type = 'text';
keyInput.placeholder = 'Enter key';
keyInput.style.backgroundColor = '#1E1E1E';
keyInput.style.color = 'white';
keyInput.style.border = '1px solid #444444';
keyInput.style.borderRadius = '5px';
keyInput.style.padding = '5px';
keyInput.style.marginBottom = '-4px';
keyValueContainer.appendChild(keyInput);

// Create input for value
const valueInput = document.createElement('textarea');
valueInput.placeholder = 'Enter value';
valueInput.style.backgroundColor = '#1E1E1E';
valueInput.style.color = 'white';
valueInput.style.border = '1px solid #444444';
valueInput.style.borderRadius = '5px';
valueInput.style.padding = '5px';
valueInput.style.height = '80px';
valueInput.style.overflowWrap = 'break-word';
valueInput.style.overflow = 'auto';
valueInput.style.marginBottom = '-4px';
keyValueContainer.appendChild(valueInput);


// Create button to add key-value pair
const addEntryButton = document.createElement('button');
addEntryButton.innerText = 'Add Entry';
    addEntryButton.innerText = 'Add Entry';
    addEntryButton.style.padding = '10px 20px';
    addEntryButton.style.border = '0.2px solid #4E4E4E';
    addEntryButton.style.backgroundColor = '#2F2F2F';
    addEntryButton.style.color = '#fff';
    addEntryButton.style.borderRadius = '50px';
    addEntryButton.style.cursor = 'pointer';

    addEntryButton.onmouseover = () => {
        addEntryButton.style.backgroundColor = '#424242';
    };
    addEntryButton.onmouseout = () => {
        addEntryButton.style.backgroundColor = 'transparent';
    };

// Adding Entries
let currentEditingKey = null; // This keeps track of the current key being edited

// Add or Edit Entry Button
addEntryButton.onclick = function () {
    if (!selectedProfile) {
        alert('Please select a profile before adding entries.');
        return;
    }

    const key = keyInput.value.trim();
    const value = `<Event: ${valueInput.value.trim()}>`;
    const probability = probabilityInput.value.trim();
    const timeRange = timeRangeInput.value.trim();
    const fullKey = `${selectedProfile}.events:${key}`;

    if (key && value) {
        // Check if we are editing an existing entry
        if (currentEditingKey) {
            // Check if we are attempting to edit to a key that already exists
            if (currentEditingKey !== fullKey && localStorage.getItem(fullKey)) {
                alert('An entry with this key already exists. Please use a different key.');
                return;
            }

            // Remove the old entry if the key has changed
            if (currentEditingKey !== fullKey) {
                localStorage.removeItem(currentEditingKey);
            }

            // Update or add the new entry
            const entryData = {
                value: value,
                probability: probability || '100',
                timeRange: timeRange || '0-24'
            };
            localStorage.setItem(fullKey, JSON.stringify(entryData));
            currentEditingKey = null; // Reset the editing key

        } else {
            // If adding a new entry
            if (!localStorage.getItem(fullKey)) {
                const entryData = {
                    value: value,
                    probability: probability || '100',
                    timeRange: timeRange || '0-24'
                };
                localStorage.setItem(fullKey, JSON.stringify(entryData));
            } else {
                alert('Entry with this key already exists. Please use a different key.');
                return;
            }
        }

        loadEntries();

        // Clear the input fields after adding/editing the entry
        keyInput.value = '';
        valueInput.value = '';
        probabilityInput.value = '100';
        timeRangeInput.value = '0-24';
    }
};
keyValueContainer.appendChild(addEntryButton);

// Append containers to profilePanel
eventsProfilePanel.appendChild(profileListContainer);
eventsProfilePanel.appendChild(keyValueContainer);



    // Load saved profiles and entries
    let selectedProfile = localStorage.getItem('selectedProfile.events');

    function loadProfiles() {
        profileList.innerHTML = '';
        for (let key in localStorage) {
            if (key.startsWith('events.profile:')) {
                const profileName = key.replace('events.profile:', '');
                const listItem = document.createElement('li');
                listItem.style.display = 'flex';
                listItem.style.alignItems = 'center';
                listItem.style.cursor = 'pointer';

                const nameSpan = document.createElement('span');
                nameSpan.innerText = profileName;
                nameSpan.style.flex = '1';
                listItem.appendChild(nameSpan);

                listItem.onclick = function() {
                    if (selectedProfile === profileName) {
                        selectedProfile = null;
                        localStorage.setItem('selectedProfile.events', '');
                        listItem.style.backgroundColor = '';
                        loadEntries();
                    } else {
                        selectedProfile = profileName;
                        localStorage.setItem('selectedProfile.events', selectedProfile);
                        loadEntries();
                        highlightSelectedProfile(listItem);
                    }
                };

                const deleteButton = document.createElement('button');
    //            deleteButton.innerText = 'x';
deleteButton.style.backgroundColor = 'transparent';
deleteButton.style.borderRadius = '50%';
deleteButton.style.marginLeft = '10px';
deleteButton.style.border = 'none';
deleteButton.style.color = '#ffffff';
deleteButton.style.cursor = 'pointer';
deleteButton.style.padding = '14px';
deleteButton.style.width = '15px';
deleteButton.style.height = '15px';
deleteButton.style.display = 'flex';
deleteButton.style.alignItems = 'center';
deleteButton.style.justifyContent = 'center';

deleteButton.style.transition = 'background-color 0.1s';

// Hover effect
deleteButton.addEventListener('mouseenter', () => {
//    closeButton.style.transform = 'scale(1.1)';
    deleteButton.style.backgroundColor = '#676767';
});

deleteButton.addEventListener('mouseleave', () => {
//    closeButton.style.transform = 'scale(1)';
    deleteButton.style.backgroundColor = 'transparent';
});



const closeIcon2 = document.createElement('span');
closeIcon2.innerText = '✕';
closeIcon2.style.fontSize = '16px';
closeIcon2.style.color = '#ffffff';
closeIcon2.style.position = 'relative';
closeIcon2.style.top = '-1px'; // Adjust this value to move the character up

deleteButton.appendChild(closeIcon2);



deleteButton.onclick = function(event) {
    event.stopPropagation();
    localStorage.removeItem(`events.profile:${profileName}`);
        if (selectedProfile === profileName) {
            selectedProfile = null;
            localStorage.setItem('selectedProfile.events', '');
        }
    loadProfiles();
    loadEntries();
};
listItem.appendChild(deleteButton);

if (selectedProfile === profileName) {
    highlightSelectedProfile(listItem);
}
profileList.appendChild(listItem);
        }
    }
}

function openAddProfileDialog() {
    const dialog = document.createElement('div');
    dialog.style.position = 'fixed';
    dialog.style.top = '50%';
    dialog.style.left = '50%';
    dialog.style.transform = 'translate(-50%, -50%)';
    dialog.style.backgroundColor = '#424242';
    dialog.style.padding = '20px';
    dialog.style.boxShadow = '0 0 10px rgba(0,0,0,0.5)';
    dialog.style.zIndex = '1100';

    const input = document.createElement('input');
    input.type = 'text';
    input.placeholder = 'Enter profile name';
    dialog.appendChild(input);

    const addButton = document.createElement('button');
    addButton.innerText = 'Add';
    addButton.style.marginLeft = '10px';
    addButton.onclick = function() {
        const profileName = input.value.trim();
        if (profileName) {
            // Perform a case-insensitive check for existing profiles
            const existingProfiles = Object.keys(localStorage).filter(key => key.startsWith('events.profile:'));
            const profileExists = existingProfiles.some(key => key.toLowerCase() === `events.profile:${profileName.toLowerCase()}`);

            if (!profileExists) {
                localStorage.setItem(`events.profile:${profileName}`, JSON.stringify({}));
                loadProfiles();
                document.body.removeChild(dialog);
            } else {
                alert('Profile name already exists. Please choose a different name.');
            }
        }
    };
    dialog.appendChild(addButton);

    const cancelButton = document.createElement('button');
    cancelButton.innerText = 'Cancel';
    cancelButton.style.marginLeft = '10px';
    cancelButton.onclick = function() {
        document.body.removeChild(dialog);
    };
    dialog.appendChild(cancelButton);

    document.body.appendChild(dialog);
}


function loadEntries() {
    entriesList.innerHTML = '';
    // Add header back after clearing
    if (selectedProfile) {
        const prefix = `${selectedProfile}.events:`.toLowerCase();

        for (let key in localStorage) {
            if (key.toLowerCase().startsWith(prefix)) {
                const entryData = JSON.parse(localStorage.getItem(key));
                const row = document.createElement('div');
                    row.style.padding = '10px';
                    row.style.margin = '5px 0';
                    row.style.borderRadius = '10px';
                    row.style.marginBottom = '12px';
                    row.style.backgroundColor = '#424242';
                    row.style.display = 'flex';
                    row.style.alignItems = 'center';

                    // Create cells for key, value, probability, and time range
                    const keyCell = document.createElement('div');
                    keyCell.innerText = key.split(':')[1];
                    keyCell.style.padding = '5px';
                    keyCell.style.width = '15%';
                    row.appendChild(keyCell);

                    const valueCell = document.createElement('div');
                    valueCell.innerText = entryData.value.replace(/^<Event:\s*/, '').slice(0, -1); // Remove surrounding brackets
                    valueCell.style.padding = '5px';
                    valueCell.style.width = '60%';
                    row.appendChild(valueCell);

                    const probabilityCell = document.createElement('div');
                    probabilityCell.innerText = `${entryData.probability}%`;
                    probabilityCell.style.padding = '5px';
                    probabilityCell.style.width = '10%';
                    row.appendChild(probabilityCell);

                    const timeRangeCell = document.createElement('div');
                    timeRangeCell.innerText = entryData.timeRange;
                    timeRangeCell.style.padding = '5px';
                    timeRangeCell.style.width = '10%';
                    row.appendChild(timeRangeCell);

                    // Add remove button for each entry
                    const actionCell = document.createElement('div');
                    actionCell.style.padding = '5px';
                    actionCell.style.width = '5%';
                    const removeButton = document.createElement('button');
                //    removeButton.innerText = '✕';
removeButton.style.backgroundColor = 'transparent';
removeButton.style.border = 'none';
removeButton.style.cursor = 'pointer';
removeButton.style.display = 'flex';
removeButton.style.alignItems = 'center';
removeButton.style.justifyContent = 'center';
removeButton.style.width = '100%';
removeButton.style.height = '100%';
removeButton.style.transition = 'background-color 0.2s ease';
removeButton.style.borderRadius = '50%';
removeButton.style.width = '28px';
removeButton.style.height = '28px';
removeButton.style.marginLeft = '-3px';
removeButton.style.boxSizing = 'border-box';
                    removeButton.onclick = function() {
                        localStorage.removeItem(key);
                        loadEntries();
                    };

const closeIcon1 = document.createElement('span');
closeIcon1.innerText = '✕';
closeIcon1.style.fontSize = '16px';
closeIcon1.style.position = 'relative';
closeIcon1.style.color = '#ffffff';
closeIcon1.style.top = '-1px'; // Adjust this value to move the character up

                // Append the span to the button
                    removeButton.appendChild(closeIcon1);
                    actionCell.appendChild(removeButton);
                    row.appendChild(actionCell);

// Hover effect
removeButton.addEventListener('mouseenter', () => {
    removeButton.style.backgroundColor = '#676767';
});

removeButton.addEventListener('mouseleave', () => {
    removeButton.style.backgroundColor = 'transparent';
});


// Make the row editable when clicked
// Make the row editable when clicked
row.onclick = function() {
    keyInput.value = key.split(':')[1]; // If key processing remains as is
    valueInput.value = entryData.value.replace(/^<Event:\s*/, '').slice(0, -1); // Remove <Event: > prefix and surrounding brackets
    probabilityInput.value = entryData.probability;
    timeRangeInput.value = entryData.timeRange;
    currentEditingKey = key; // Set the current key for editing
};

                    entriesList.appendChild(row);
                }
            }
        }
    }





    function highlightSelectedProfile(selectedItem) {
        // Remove highlight from all items
        Array.from(profileList.children).forEach(item => {
            item.style.backgroundColor = '';
        });
        // Highlight the selected item
        selectedItem.style.backgroundColor = '#444444';
        selectedItem.style.borderRadius = '10px';
        selectedItem.style.padding = '10px';
    }

    loadProfiles();
    loadEntries();

    // Append profilePanel to body
    document.body.appendChild(eventsProfilePanel);
}

}

// ==================================================================== RULES ===================================================================
function RulesScript() {

    // Custom texts to cycle through
    let customRules = [];

    let currentIndex = 0;

    // Function to determine the current rule index by scanning last two messages
    function determineCurrentIndex() {
        const messageItems = document.querySelectorAll('li[class^="messageListItem_"]');

        if (messageItems.length >= 1) {
            // Check the last message first
            const lastMessage = Array.from(messageItems[messageItems.length - 1].querySelectorAll('span')).map(span => span.innerText).join('') || messageItems[messageItems.length - 1].innerText;

            for (let i = 0; i < customRules.length; i++) {
                if (lastMessage.includes(`<Rule${i + 1}:`)) {
                    currentIndex = (i + 1) % customRules.length;
                    return;
                }
            }
        }

        // If not found in the last message, check the second to last message
        if (messageItems.length >= 2) {
            const secondLastMessage = Array.from(messageItems[messageItems.length - 2].querySelectorAll('span')).map(span => span.innerText).join('') || messageItems[messageItems.length - 2].innerText;

            for (let i = 0; i < customRules.length; i++) {
                if (secondLastMessage.includes(`<Rule${i + 1}:`)) {
                    currentIndex = (i + 1) % customRules.length;
                    return;
                }
            }
        }
    }

    // Expose necessary elements to be used by the second script
    window.customRuleLogic = {
        customRules,
        determineCurrentIndex,
        getCurrentText: function() {
            determineCurrentIndex();
            const customRule = '\n' + customRules[currentIndex];
            currentIndex = (currentIndex + 1) % customRules.length;
            return customRule;
        }
    };

    // Create Button and Panel UI for Local Storage Key Management


window.manageRulesButton = document.createElement('div');
window.manageRulesButton.innerHTML = `
    <button id="toggle-rules-panel"
        style="
            position: relative;
            top: 10px;
            right: 0px;
            left: 10px;
            padding: 7px 15px;
            background: transparent;
            color: #b0b0b0;
            border: none;
            border-radius: 8px;
            font-size: 16px;
            text-align: left;
            cursor: pointer;
            width: 90%;
            display: flex;
            align-items: center;
            gap: 10px;
            transition: background-color 0.1s, color 0.1s;
            z-index: 1001;">
        <svg fill="#B0B0B0" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16px" height="16px" viewBox="0 0 492.508 492.508" xml:space="preserve" style="padding-right: 0px; margin-left: 1px;">
            <g id="SVGRepo_bgCarrier" stroke-width="0"></g>
            <g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g>
            <g id="SVGRepo_iconCarrier">
                <g>
                    <g>
                        <path d="M199.493,402.145c0-10.141-8.221-18.361-18.36-18.361H42.475c-10.139,0-18.36,8.221-18.36,18.361 c0,3.195,0.818,6.199,2.255,8.816H0v38.067h223.607v-38.067h-26.369C198.674,408.343,199.493,405.34,199.493,402.145z"></path>
                        <path d="M175.898,88.224l117.157,74.396c9.111,4.643,20.43,1.678,26.021-7.129l5.622-8.85c5.938-9.354,3.171-21.75-6.182-27.69 L204.592,46.608c-9.352-5.939-21.748-3.172-27.688,6.182l-5.622,8.851C165.692,70.447,167.82,81.952,175.898,88.224z"></path>
                        <path d="M492.456,372.433l-0.082-1.771l-0.146-1.672c-0.075-1.143-0.235-2.159-0.375-3.204c-0.562-4.177-1.521-7.731-2.693-10.946 c-2.377-6.386-5.738-11.222-9.866-14.845c-1.027-0.913-2.126-1.714-3.218-2.528l-3.271-2.443 c-2.172-1.643-4.387-3.218-6.587-4.815c-2.196-1.606-4.419-3.169-6.644-4.729c-2.218-1.571-4.445-3.125-6.691-4.651 c-4.468-3.089-8.983-6.101-13.51-9.103l-6.812-4.464l-6.85-4.405c-4.58-2.911-9.167-5.813-13.785-8.667 c-4.611-2.865-9.24-5.703-13.896-8.496l-13.979-8.363l-14.072-8.22l-14.149-8.096l-14.219-7.987l-14.287-7.882l-14.354-7.773 c-4.802-2.566-9.599-5.137-14.433-7.653c-4.822-2.529-9.641-5.071-14.498-7.548l-4.398,6.928l-22.17-10.449l24.781-39.026 l-117.156-74.395l-60.944,95.974l117.157,74.395l24.781-39.026l18.887,15.622l-4.399,6.929c4.309,3.343,8.657,6.619,12.998,9.91 c4.331,3.305,8.698,6.553,13.062,9.808l13.14,9.686l13.211,9.577l13.275,9.474l13.346,9.361l13.422,9.242l13.514,9.095 c4.51,3.026,9.045,6.009,13.602,8.964c4.547,2.967,9.123,5.882,13.707,8.792l6.898,4.324l6.936,4.266 c4.643,2.818,9.289,5.625,13.985,8.357c2.337,1.383,4.689,2.739,7.055,4.078c2.358,1.349,4.719,2.697,7.106,4 c2.383,1.312,4.75,2.646,7.159,3.912l3.603,1.922c1.201,0.64,2.394,1.296,3.657,1.837c5.036,2.194,10.841,3.18,17.63,2.614 c3.409-0.305,7.034-0.949,11.054-2.216c1.006-0.317,1.992-0.606,3.061-1.023l1.574-0.58l1.639-0.68 c2.185-0.91,4.523-2.063,7.059-3.522C492.513,377.405,492.561,374.799,492.456,372.433z"></path>
                        <path d="M67.897,261.877l113.922,72.341c9.354,5.938,21.75,3.172,27.689-6.181l5.621-8.852c5.592-8.808,3.462-20.311-4.615-26.583 L93.358,218.207c-9.111-4.642-20.43-1.678-26.022,7.13l-5.62,8.85C55.775,243.541,58.543,255.938,67.897,261.877z"></path>
                    </g>
                </g>
            </g>
        </svg>
        Manage Rules
    </button>
`;


const rulesButtonElement = manageRulesButton.querySelector('button');
rulesButtonElement.onmouseover = () => {
    rulesButtonElement.style.backgroundColor = '#212121';
    rulesButtonElement.style.color = '#ffffff';
};
rulesButtonElement.onmouseout = () => {
    rulesButtonElement.style.backgroundColor = 'transparent';
    rulesButtonElement.style.color = '#b0b0b0';
};

const rulesPanel = document.createElement('div');
rulesPanel.style.position = 'fixed';
rulesPanel.style.top = '50%';
rulesPanel.style.left = '50%';
rulesPanel.style.transform = 'translate(-50%, -50%)';
// Size different for Mobile and Desktop
if (window.innerWidth <= 768) {
    rulesPanel.style.width = '90%';
    rulesPanel.style.height = '90%';
} else {
    rulesPanel.style.width = '800px';
    rulesPanel.style.height = '700px';
}
rulesPanel.style.backgroundColor = '#2f2f2f';
rulesPanel.style.padding = '20px';
rulesPanel.style.overflow = 'hidden'; // Prevent full panel scrolling
rulesPanel.style.display = 'none';
rulesPanel.style.zIndex = 1000;
rulesPanel.style.borderRadius = '10px';
document.body.appendChild(rulesPanel);

const title = document.createElement('h2');
title.innerText = 'Manage Rules';
title.style.textAlign = 'center';
title.style.color = '#ffffff';
title.style.fontSize = '24px';
title.style.fontWeight = '550';
title.style.marginBottom = '20px';
rulesPanel.appendChild(title);

const closeButton = document.createElement('button');
closeButton.innerText = '✕';
closeButton.style.position = 'absolute';
closeButton.style.borderRadius = '50%';
closeButton.style.color = '#ffffff';
closeButton.style.top = '20px';
closeButton.style.right = '20px';
closeButton.style.backgroundColor = 'transparent';
closeButton.style.cursor = 'pointer';

closeButton.addEventListener('mouseenter', () => {
    closeButton.style.backgroundColor = '#676767';
});
closeButton.addEventListener('mouseleave', () => {
    closeButton.style.backgroundColor = 'transparent';
});

closeButton.addEventListener('click', () => {
    rulesPanel.style.display = 'none';
});
rulesPanel.appendChild(closeButton);

const rulesListContainer = document.createElement('div');
rulesListContainer.style.height = 'calc(100% - 180px)'; // Adjust height to leave space for header and button
rulesListContainer.style.overflowY = 'auto'; // Allow only the rules list to scroll
rulesPanel.appendChild(rulesListContainer);

manageRulesButton.addEventListener('click', () => {
    rulesPanel.style.display = rulesPanel.style.display === 'none' ? 'block' : 'none';
    renderPanel();
});

function renderPanel() {
    rulesListContainer.innerHTML = '';

    customRules.forEach((rule, index) => {
        const ruleContainer = document.createElement('div');
        ruleContainer.style.marginBottom = '15px';
        ruleContainer.style.display = 'flex';
        ruleContainer.style.alignItems = 'center';
        ruleContainer.style.width = '95%';
        ruleContainer.style.gap = '5px'; // Reduced gap to bring elements closer

        const ruleLabel = document.createElement('label');
        ruleLabel.textContent = `Rule ${index + 1}:`;
        ruleLabel.style.color = 'white';
        ruleLabel.style.marginLeft = '5%';
        ruleLabel.style.flex = '0.5'; // Reduced flex to bring the label closer to the input
        ruleContainer.appendChild(ruleLabel);

        // Set the textarea value to the rule text rather than using it as a placeholder
        const ruleInput = document.createElement('textarea');
        ruleInput.value = rule.replace(/<Rule\d+: (.*?)>/, '$1'); // Set the inner text as the value for editing
        ruleInput.style.flex = '2';
        ruleInput.style.padding = '5px'; // Added more padding for easier tapping
        ruleInput.style.borderRadius = '5px';
        ruleInput.style.border = '0.5px solid #444444';
        ruleInput.style.backgroundColor = '#1E1E1E';
        ruleInput.style.color = 'gray';
        ruleInput.style.overflowY = 'hidden'; // Handle vertical overflow automatically
        ruleInput.style.overflowX = 'hidden'; // Prevent horizontal overflow
        ruleInput.style.maxWidth = '100%'; // Prevent textarea from extending beyond container width
        ruleInput.style.boxSizing = 'border-box'; // Ensure padding is included in width calculation
        ruleInput.style.resize = 'none'; // Disable manual resizing to avoid visual clutter

        // Adjust height based on input content
        function adjustHeight(element) {
            element.style.height = 'auto'; // Reset height to calculate the new height
            element.style.height = `${element.scrollHeight}px`; // Set height to match content
        }

        // Adjust height initially to fit content on render
        adjustHeight(ruleInput);

        ruleInput.addEventListener('input', () => {
            adjustHeight(ruleInput);
            ruleInput.style.color = '#D16262'; // Indicate unsaved changes
        });

        ruleContainer.appendChild(ruleInput);

        const updateButton = document.createElement('button');
        updateButton.textContent = 'Update';
        updateButton.style.padding = '5px 10px';
        updateButton.style.border = 'none';
        updateButton.style.backgroundColor = '#1E1E1E';
        updateButton.style.color = 'white';
        updateButton.style.borderRadius = '5px';
        updateButton.style.cursor = 'pointer';
        updateButton.addEventListener('click', () => {
            customRules[index] = `<Rule${index + 1}: ${ruleInput.value}>`;
            updateLocalStorageKeys();
            ruleInput.style.color = 'black'; // Change color to indicate saved state
        });
        ruleContainer.appendChild(updateButton);

        const deleteButton = document.createElement('button');
        deleteButton.textContent = 'Delete';
        deleteButton.style.padding = '5px 10px';
        deleteButton.style.border = 'none';
        deleteButton.style.backgroundColor = '#1E1E1E';
        deleteButton.style.color = 'white';
        deleteButton.style.marginLeft = '5px';
        deleteButton.style.borderRadius = '5px';
        deleteButton.style.cursor = 'pointer';
        deleteButton.addEventListener('click', () => {
            customRules.splice(index, 1);
            updateLocalStorageKeys();
            renderPanel();
        });
        ruleContainer.appendChild(deleteButton);

        // Move rule up/down container
        const moveContainer = document.createElement('div');
        moveContainer.style.display = 'flex';
        moveContainer.style.flexDirection = 'column';
        moveContainer.style.gap = '3px';

        // Move rule up
        if (index > 0) {
            const upButton = document.createElement('button');
            upButton.textContent = '▲';
            upButton.style.padding = '3px';
            upButton.style.border = 'none';
            upButton.style.backgroundColor = 'transparent';
            upButton.style.color = 'white';
            upButton.style.borderRadius = '5px';
            upButton.style.cursor = 'pointer';
            upButton.addEventListener('click', () => {
                [customRules[index - 1], customRules[index]] = [customRules[index], customRules[index - 1]];
                updateLocalStorageKeys();
                renderPanel();
            });
            moveContainer.appendChild(upButton);
        }

        // Move rule down
        if (index < customRules.length - 1) {
            const downButton = document.createElement('button');
            downButton.textContent = '▼';
            downButton.style.padding = '3px';
            downButton.style.border = 'none';
            downButton.style.backgroundColor = 'transparent';
            downButton.style.color = 'white';
            downButton.style.borderRadius = '5px';
            downButton.style.cursor = 'pointer';
            downButton.addEventListener('click', () => {
                [customRules[index], customRules[index + 1]] = [customRules[index + 1], customRules[index]];
                updateLocalStorageKeys();
                renderPanel();
            });
            moveContainer.appendChild(downButton);
        }

        ruleContainer.appendChild(moveContainer);
        rulesListContainer.appendChild(ruleContainer);
    });

    const addButton = document.createElement('button');
    addButton.textContent = 'Add Rule';
    addButton.style.margin = '15px auto';
    addButton.style.display = 'block';
    addButton.style.padding = '10px';
    addButton.style.border = 'none';
    addButton.style.width = '90%';
    addButton.style.backgroundColor = '#e0e0e0';
    addButton.style.borderRadius = '20px';
    addButton.style.cursor = 'pointer';
    addButton.addEventListener('click', () => {
        const newRule = `<Rule${customRules.length + 1}: Define your rule here>`;
        customRules.push(newRule);
        updateLocalStorageKeys();
        renderPanel();
    });
    rulesPanel.appendChild(addButton);

    // Adjust height for all textareas after rendering the panel
    adjustAllHeights();
}

// Initial adjustment when loading the panel
function adjustAllHeights() {
    const textareas = rulesListContainer.querySelectorAll('textarea');
    textareas.forEach((textarea) => {
        textarea.style.height = 'auto'; // Reset height to calculate the new height
        textarea.style.height = `${textarea.scrollHeight}px`; // Set height to match content
    });
}


function updateLocalStorageKeys() {
    customRules.forEach((_, index) => localStorage.removeItem(`Rule${index + 1}`));
    customRules.forEach((rule, index) => {
        localStorage.setItem(`Rule${index + 1}`, rule);
    });
}

    // Load rules from localStorage
    for (let i = 0; i < localStorage.length; i++) {
        const savedRule = localStorage.getItem(`Rule${i + 1}`);
        if (savedRule) {
            customRules.push(savedRule);
        }
    }
}

// ===================================================================== MP3 ====================================================================
function mp3Script() {

// Function to get API key from local storage or prompt user to input it
function getApiKey() {
    let apiKey = localStorage.getItem('google_cloud_api_key');
    return apiKey;
}

// Function to set the API key in local storage
document.addEventListener('input', (event) => {
    if (event.target.id === 'api-key-input') {
        const apiKey = event.target.value;
        if (apiKey) {
            localStorage.setItem('google_cloud_api_key', apiKey);
            alert('API key saved successfully.');
        }
    }
});

// Fetch the API key
let API_KEY = getApiKey();

const API_URL = `https://speech.googleapis.com/v1/speech:recognize?key=${API_KEY}`;

// Create a button to toggle the transcription panel
window.mp3ToggleButton = document.createElement('div');
mp3ToggleButton.innerHTML = `
    <button id="toggle-transcription-panel"
        style="
            display: flex;
            align-items: center;
            gap: 8px;
            position: relative;
            top: 10px;
            right: 0px;
            left: 10px;
            padding: 7px 15px;
            background: transparent;
            color: #b0b0b0;
            border: none;
            border-radius: 8px;
            font-size: 16px;
            text-align: left;
            cursor: pointer;
            width: 90%;
            transition: background-color 0.1s, color 0.1s;
            z-index: 1001;">
        <svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" xml:space="preserve" width="20px" height="20px" style="margin-right: -2px;">
            <path d="M6 11L6 13" stroke="#B0B0B0" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
            <path d="M9 9L9 15" stroke="#B0B0B0" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
            <path d="M15 9L15 15" stroke="#B0B0B0" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
            <path d="M18 11L18 13" stroke="#B0B0B0" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
            <path d="M12 11L12 13" stroke="#B0B0B0" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
        </svg>
        Show Transcript
    </button>
`;


const buttonElement = mp3ToggleButton.querySelector('button');
buttonElement.onmouseover = () => {
    buttonElement.style.backgroundColor = '#212121';
    buttonElement.style.color = '#ffffff';
};
buttonElement.onmouseout = () => {
    buttonElement.style.backgroundColor = 'transparent';
    buttonElement.style.color = '#b0b0b0';
};

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

// Add a simple panel to the webpage
const panelHTML = `
    <div id="transcription-panel" style="display: none;">
        <h3>MP3 Transcription Tool</h3>
        <input type="text" id="api-key-input" placeholder="Enter Google Cloud API key here" />
        <input type="text" id="mp3-url" placeholder="Enter MP3 URL here" />
        <button id="transcribe-button">Transcribe</button>
        <textarea id="transcription-result" placeholder="Transcript will appear here..." readonly></textarea>
    </div>
`;

document.body.insertAdjacentHTML('beforeend', panelHTML);

// Set the API key input value if it exists in local storage
document.addEventListener('DOMContentLoaded', () => {
    const apiKeyInput = document.getElementById('api-key-input');
    if (apiKeyInput) {
        const savedApiKey = getApiKey();
        if (savedApiKey) {
            apiKeyInput.value = savedApiKey;
            API_KEY = savedApiKey;
        }
    }
});

// Add styles for the panel
GM_addStyle(`
    #transcription-panel {
        position: fixed;
        bottom: 50px;
        right: 10px;
        width: 300px;
        background: #f8f9fa;
        border: 1px solid #ccc;
        padding: 10px;
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
        z-index: 9999;
        font-family: Arial, sans-serif;
    }
    #transcription-panel h3 {
        margin: 0 0 10px;
        font-size: 16px;
    }
    #transcription-panel input, #transcription-panel textarea {
        width: 100%;
        margin-bottom: 10px;
        padding: 5px;
        box-sizing: border-box;
    }
    #transcription-panel button {
        width: 100%;
        padding: 5px;
        cursor: pointer;
        background: #007bff;
        color: white;
        border: none;
        border-radius: 3px;
    }
`);

// Add event listener to the toggle button
document.addEventListener('click', (event) => {
    // Check if the clicked element is the button
    const button = event.target.closest('#toggle-transcription-panel');
    if (button) {
        const panel = document.getElementById('transcription-panel');
        if (panel) {
            if (panel.style.display === 'none') {
                panel.style.display = 'block';
                button.innerText = 'Hide MP3 Transcription';
            } else {
                panel.style.display = 'none';
                button.innerText = 'Show MP3 Transcription';
            }
        } else {
            console.error('Transcription panel not found!');
        }
    }
});



    // Add event listener to the Transcribe button
    document.getElementById('transcribe-button').addEventListener('click', transcribe);
    // Function to transcribe the entered MP3 URL
    function transcribe() {
        const mp3Url = document.getElementById('mp3-url').value.trim();
        if (!mp3Url) {
            alert('Please enter a valid MP3 URL.');
            return;
        }

        // Check if the transcript already exists in local storage
        const storedTranscript = localStorage.getItem(mp3Url);
        if (storedTranscript) {
            document.getElementById('transcription-result').value = storedTranscript;
            return;
        }

        // Fetch MP3 file using GM_xmlhttpRequest and process it
        GM_xmlhttpRequest({
            method: 'GET',
            url: mp3Url,
            responseType: 'arraybuffer', // Required for audio data
            onload: (response) => {
                // Convert the audio file to Base64
                const audioBase64 = arrayBufferToBase64(response.response);

                // Send the Base64-encoded audio to Google Cloud Speech-to-Text API
                sendToGoogleCloud(audioBase64, mp3Url);
            },
            onerror: (err) => {
                alert('Failed to fetch the MP3 file.');
                console.error(err);
            },
        });
    }

    // Function to send the Base64 audio data to Google Cloud Speech-to-Text API
    function sendToGoogleCloud(audioBase64, mp3Url) {
        GM_xmlhttpRequest({
            method: 'POST',
            url: API_URL,
            headers: { 'Content-Type': 'application/json' },
            data: JSON.stringify({
                config: {
                    encoding: 'MP3',
                    sampleRateHertz: 16000,
                    languageCode: 'en-US',
                },
                audio: {
                    content: audioBase64,
                },
            }),
            onload: (response) => {
                const result = JSON.parse(response.responseText);
                if (result.error) {
                    alert(`Error: ${result.error.message}`);
                } else {
                    const transcript = result.results
                        ?.map((r) => r.alternatives[0].transcript)
                        .join('\n');
                    document.getElementById('transcription-result').value =
                        transcript || 'No transcript found.';

                    // Store the transcript in local storage
                    localStorage.setItem(mp3Url, transcript || 'No transcript found.');

                    // Limit local storage to 3 entries
                    manageLocalStorageLimit();

                    // Show "Transcript done!" message
                    showTranscriptionDoneMessage();
                }
            },
            onerror: (err) => {
                alert('Failed to process the transcription.');
                console.error(err);
            },
        });
    }

    // Function to convert ArrayBuffer to Base64
    function arrayBufferToBase64(buffer) {
        const binary = [];
        const bytes = new Uint8Array(buffer);
        const len = bytes.byteLength;
        for (let i = 0; i < len; i++) {
            binary.push(String.fromCharCode(bytes[i]));
        }
        return btoa(binary.join(''));
    }

    // Observe the conversation for changes and detect MP3 links
    const observer = new MutationObserver(() => {
        const messageItems = document.querySelectorAll('div[class*="messageContent_"]');
        const lastMessage = messageItems[messageItems.length - 1];

        if (lastMessage) {
            const mp3LinkMatch = lastMessage.innerText.match(/https:\/\/files\.shapes\.inc\/.*\.mp3/);
            if (mp3LinkMatch) {
                const mp3Link = mp3LinkMatch[0];
                const storedLink = localStorage.getItem('lastMp3Link');

                // Check if the link is new or different
                if (mp3Link !== storedLink) {
                    localStorage.setItem('lastMp3Link', mp3Link); // Store the new link
                    document.getElementById('mp3-url').value = mp3Link; // Populate the input
                    transcribe(); // Automatically transcribe the new link
                }
            }
        }
    });

    // Start observing the document body for new messages
    observer.observe(document.body, { childList: true, subtree: true });

    // Function to manage local storage limit of 3 entries
    function manageLocalStorageLimit() {
        const keys = Object.keys(localStorage).filter((key) => key.startsWith('http'));
        if (keys.length > 10) {
            // Remove oldest entries until only 3 remain
            while (keys.length > 10) {
                localStorage.removeItem(keys.shift());
            }
        }
    }

    // Function to show "Transcript done!" message
    function showTranscriptionDoneMessage() {
        let messageDiv = document.getElementById('transcription-done-message');
        if (!messageDiv) {
            messageDiv = document.createElement('div');
            messageDiv.id = 'transcription-done-message';
            messageDiv.innerText = 'Transcript done!';
            document.body.appendChild(messageDiv);
        }

        messageDiv.style.display = 'block';
        setTimeout(() => {
            messageDiv.style.display = 'none';
        }, 3000);
    }

}

// =================================================================== STYLES ===================================================================
function StylesScript() {

    // Add custom CSS rule to modify the channel text area
    const style = document.createElement('style');
    style.innerHTML = `
        .channelTextArea_bdf0de {
            position: relative;
            width: 120%;
            text-indent: 0;
            border-radius: 8px;
        }
        .themedBackground_bdf0de {
            background: #2F2F2F;
        }
        .chatContent_a7d72e {
            position: relative;
            display: flex;
            flex-direction: column;
            min-width: 0;
            min-height: 0;
            flex: 1 1 auto;
            background: #212121 !important;
        }

        .theme-dark .container_ee69e0 {
            background: #191919;
        }
        .theme-dark .themed_fc4f04 {
            background: #212121;
        }

        .footer_f8ec41 {
            background: #131313;
        }
        .theme-dark .container_b2ca13 {
            background: #191919;
        }

.wrapper_fea3ef {
            background-color: #131313;
    display: none !important;

}



    `;
    document.head.appendChild(style);

    // Function to hide the targeted elements
    function hideElements() {
        // Select all elements that match the provided pattern
        const elements = document.querySelectorAll("[id^='message-accessories-'] > article > div > div > div.embedProvider_b0068a.embedMargin_b0068a, [id^='message-accessories-'] > article > div > div > div.embedTitle_b0068a.embedMargin_b0068a, .buttons_bdf0de .expression-picker-chat-input-button.buttonContainer_bdf0de, .channelAppLauncher_df39bd .buttonContainer_df39bd.app-launcher-entrypoint");

        // Iterate over each element and hide it
        elements.forEach(element => {
            element.style.display = 'none';
        });
    }

    // Run the function initially to hide elements present at page load
    hideElements();

    // Observe mutations to the DOM and hide elements when new ones are added
    const observer = new MutationObserver(hideElements);
    observer.observe(document.body, { childList: true, subtree: true });

// Create the toggleButton div
// Create the toggleButton div
window.serverbartoggleButton = document.createElement('div');
serverbartoggleButton.innerHTML = `
    <button id="toggle-server-panel"
        style="
            display: flex;
            align-items: center;
            gap: 8px; /* Add spacing between icon and text */
            position: relative;
            top: 10px;
            right: 0px;
            left: 10px;
            padding: 7px 15px;
            background: transparent;
            color: #b0b0b0;
            border: none;
            border-radius: 8px;
            font-size: 16px;
            text-align: left;
            cursor: pointer;
            width: 90%;
            transition: background-color 0.1s, color 0.1s;
            z-index: 1001;">
        <svg width="16px" height="16px" viewBox="0 0 16 16" style="padding-right: 0px; margin-left: 2px" xmlns="http://www.w3.org/2000/svg" fill="#000000">
            <g fill="#B0B0B0">
                <path d="m 6.5 14 v -12 h -5 v 12 z m 0 0" fill-opacity="0.34902"></path>
                <path d="m 3 1 c -1.644531 0 -3 1.355469 -3 3 v 8 c 0 1.644531 1.355469 3 3 3 h 10 c 1.644531 0 3 -1.355469 3 -3 v -8 c 0 -1.644531 -1.355469 -3 -3 -3 z m 0 2 h 10 c 0.570312 0 1 0.429688 1 1 v 8 c 0 0.570312 -0.429688 1 -1 1 h -10 c -0.570312 0 -1 -0.429688 -1 -1 v -8 c 0 -0.570312 0.429688 -1 1 -1 z m 0 0"></path>
                <path d="m 6 2 h 1 v 12 h -1 z m 0 0"></path>
            </g>
        </svg>
        Toggle Sidebar
    </button>
`;

// Append the toggleButton to the desired parent element (e.g., `DCstoragePanel`)
//window.DCstoragePanel.appendChild(serverbartoggleButton);

// Function to toggle .itemsContainer_fea3ef visibility
function servertoggleItemsContainer() {
    const serveritemsContainer = document.querySelectorAll('.wrapper_fea3ef');
    serveritemsContainer.forEach(container => {
        const currentDisplay = window.getComputedStyle(container).getPropertyValue('display');

        if (currentDisplay === 'none') {
            container.setAttribute('style', 'display: flex !important;');
        } else {
            container.setAttribute('style', 'display: none !important;');
        }
    });
}


    // Add event listener to the toggle button
    serverbartoggleButton.addEventListener('click', servertoggleItemsContainer);

const serverbuttonElement = serverbartoggleButton.querySelector('button');
serverbuttonElement.onmouseover = () => {
    serverbuttonElement.style.backgroundColor = '#212121';
    serverbuttonElement.style.color = '#ffffff';
};
serverbuttonElement.onmouseout = () => {
    serverbuttonElement.style.backgroundColor = 'transparent';
    serverbuttonElement.style.color = '#b0b0b0';
};


}

// ================================================================== < > HIDER =================================================================
function HiderScript() {
    function hideEnclosedEntries() {
        const messageItems = document.querySelectorAll('li[class^="messageListItem_"]');

        messageItems.forEach(messageItem => {
            const spans = messageItem.querySelectorAll('div[class*="messageContent_"] span');

            let isHiding = false;
            spans.forEach(span => {
                const text = span.textContent.trim();

                // Start hiding when encountering '<'
                if (text.startsWith('<') && !isHiding) {
                    isHiding = true;
                }

                // Apply hiding style if within an enclosed entry
                if (isHiding) {
                    span.style.opacity = '0'; // Make it invisible
                    span.style.position = 'absolute'; // Remove it from the document flow
                }

                // Stop hiding when encountering '>'
                if (text.endsWith('>') && isHiding) {
                    isHiding = false;
                }
            });
        });
    }

    // Observe for new messages being added to the DOM
    const observer = new MutationObserver(mutations => {
        mutations.forEach(() => {
            hideEnclosedEntries();
        });
    });

    // Start observing the entire document body for changes
    observer.observe(document.body, { childList: true, subtree: true });

    // Initial run
    hideEnclosedEntries();

}

// ================================================================== NOTIFIER =================================================================
function NotifierScript() {

// Create a button to toggle the transcription panel
window.notifierToggleButton = document.createElement('div');
notifierToggleButton.innerHTML = `
    <button id="toggle-notifier-panel"
        style="
            display: flex;
            align-items: center;
            gap: 8px;
            position: relative;
            top: 10px;
            right: 0px;
            left: 10px;
            padding: 7px 15px;
            background: transparent;
            color: #b0b0b0;
            border: none;
            border-radius: 8px;
            font-size: 16px;
            text-align: left;
            cursor: pointer;
            width: 90%;
            transition: background-color 0.1s, color 0.1s;
            z-index: 1001;">
        <svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" xml:space="preserve" width="20px" height="20px" style="margin-right: -2px;">
            <path d="M6 11L6 13" stroke="#B0B0B0" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
            <path d="M9 9L9 15" stroke="#B0B0B0" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
            <path d="M15 9L15 15" stroke="#B0B0B0" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
            <path d="M18 11L18 13" stroke="#B0B0B0" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
            <path d="M12 11L12 13" stroke="#B0B0B0" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
        </svg>
        Show Notifiers
    </button>
`;

const notifierButtonElement = notifierToggleButton.querySelector('button');
notifierButtonElement.onmouseover = () => {
    notifierButtonElement.style.backgroundColor = '#212121';
    notifierButtonElement.style.color = '#ffffff';
};
notifierButtonElement.onmouseout = () => {
    notifierButtonElement.style.backgroundColor = 'transparent';
    notifierButtonElement.style.color = '#b0b0b0';
};


// Create the main panel container
const notifierPanel = document.createElement('div');
notifierPanel.id = 'lorebookManagerPanel';
notifierPanel.style.position = 'fixed';
notifierPanel.style.top = '50%';
notifierPanel.style.left = '50%';
notifierPanel.style.transform = 'translate(-50%, -50%)';
// Size different for Mobile and Desktop
if (window.innerWidth <= 768) {
    notifierPanel.style.width = '90%';
    notifierPanel.style.height = '90%';
} else {
    notifierPanel.style.width = '800px';
    notifierPanel.style.height = '700px';
}
notifierPanel.style.backgroundColor = '#2F2F2F';
notifierPanel.style.borderRadius = '20px';
notifierPanel.style.padding = '10px';
notifierPanel.style.display = 'none';
notifierPanel.style.zIndex = '1000';

// Add close button for the panel
const closeButton = document.createElement('button');
closeButton.innerText = '✕';
closeButton.style.position = 'absolute';
closeButton.style.borderRadius = '50%';
closeButton.style.color = '#ffffff';
closeButton.style.top = '20px';
closeButton.style.right = '20px';
closeButton.style.backgroundColor = 'transparent';
closeButton.style.cursor = 'pointer';

closeButton.addEventListener('mouseenter', () => {
    closeButton.style.backgroundColor = '#676767';
});
closeButton.addEventListener('mouseleave', () => {
    closeButton.style.backgroundColor = 'transparent';
});

// Hide the Lorebook Panel
closeButton.addEventListener('click', () => {
    notifierPanel.style.display = 'none';
});

// Open the Lorebook Panel
notifierToggleButton.addEventListener('click', () => {
    notifierPanel.style.display = notifierPanel.style.display === 'none' ? 'block' : 'none';
    loadProfileEntries();
    loadKeyValueEntries();
});

// Create the profiles container on the left
const profilesContainer = document.createElement('div');
profilesContainer.style.width = '200px';
profilesContainer.style.height = '100%';
profilesContainer.style.float = 'left';
profilesContainer.style.borderRight = '1px solid #676767';
profilesContainer.style.padding = '10px';
profilesContainer.style.boxSizing = 'border-box';
profilesContainer.style.overflowY = 'auto';

// Create the profile entries container
const profilesList = document.createElement('div');
profilesContainer.appendChild(profilesList);

// Create input to add new profiles
const newProfileInput = document.createElement('input');
newProfileInput.type = 'text';
newProfileInput.placeholder = 'New Profile Name';
newProfileInput.style.width = 'calc(100% - 20px)';
newProfileInput.style.marginTop = '10px';
newProfileInput.style.padding = '5px';
newProfileInput.style.borderRadius = '5px';
newProfileInput.style.border = '1px solid #676767';

// Create button to add new profiles
const addProfileButton = document.createElement('button');
addProfileButton.innerText = 'Add Profile';
addProfileButton.style.marginTop = '10px';
addProfileButton.style.padding = '5px 10px';
addProfileButton.style.cursor = 'pointer';
addProfileButton.style.backgroundColor = '#4CAF50';
addProfileButton.style.color = '#ffffff';
addProfileButton.style.border = 'none';
addProfileButton.style.borderRadius = '5px';

addProfileButton.addEventListener('click', () => {
    const profileName = newProfileInput.value.trim();
    if (profileName) {
        const profileKey = `notifier.profile:${profileName}`;
        localStorage.setItem(profileKey, '{}');
        newProfileInput.value = '';
        loadProfileEntries();
    }
});

profilesContainer.appendChild(newProfileInput);
profilesContainer.appendChild(addProfileButton);
notifierPanel.appendChild(profilesContainer);

// Create the key-value input container on the right
const keyValueContainer = document.createElement('div');
keyValueContainer.style.width = 'calc(100% - 220px)';
keyValueContainer.style.height = '100%';
keyValueContainer.style.float = 'right';
keyValueContainer.style.padding = '10px';
keyValueContainer.style.boxSizing = 'border-box';
keyValueContainer.style.overflowY = 'auto';

// Create the key-value entries container
const keyValueList = document.createElement('div');
keyValueContainer.appendChild(keyValueList);

// Create input to add new key-value pairs
const newKeyInput = document.createElement('input');
newKeyInput.type = 'text';
newKeyInput.placeholder = 'New Key';
newKeyInput.style.width = 'calc(100% - 20px)';
newKeyInput.style.marginTop = '10px';
newKeyInput.style.padding = '5px';
newKeyInput.style.borderRadius = '5px';
newKeyInput.style.border = '1px solid #676767';

const newValueInput = document.createElement('input');
newValueInput.type = 'text';
newValueInput.placeholder = 'New Value';
newValueInput.style.width = 'calc(100% - 20px)';
newValueInput.style.marginTop = '10px';
newValueInput.style.padding = '5px';
newValueInput.style.borderRadius = '5px';
newValueInput.style.border = '1px solid #676767';

// Create a datetime picker input
const newDateTimeInput = document.createElement('input');
newDateTimeInput.type = 'datetime-local';
newDateTimeInput.style.width = 'calc(100% - 20px)';
newDateTimeInput.style.marginTop = '10px';
newDateTimeInput.style.padding = '5px';
newDateTimeInput.style.borderRadius = '5px';
newDateTimeInput.style.border = '1px solid #676767';

// Create start time input with a time selector 'wheel'
const startTimeInput = document.createElement('input');
startTimeInput.type = 'time';
startTimeInput.style.width = 'calc(50% - 15px)';
startTimeInput.style.marginTop = '10px';
startTimeInput.style.marginRight = '10px';
startTimeInput.style.padding = '5px';
startTimeInput.style.borderRadius = '5px';
startTimeInput.style.border = '1px solid #676767';

// Create end time input with a time selector 'wheel'
const endTimeInput = document.createElement('input');
endTimeInput.type = 'time';
endTimeInput.style.width = 'calc(50% - 15px)';
endTimeInput.style.marginTop = '10px';
endTimeInput.style.padding = '5px';
endTimeInput.style.borderRadius = '5px';
endTimeInput.style.border = '1px solid #676767';

// Create checkbox for recurring daily events
const recurringDailyInput = document.createElement('input');
recurringDailyInput.type = 'checkbox';
recurringDailyInput.style.marginTop = '10px';
recurringDailyInput.style.marginRight = '5px';

const recurringDailyLabel = document.createElement('label');
recurringDailyLabel.innerText = 'Recurring Daily';
recurringDailyLabel.style.marginTop = '10px';
recurringDailyLabel.style.display = 'block';
recurringDailyLabel.style.cursor = 'pointer';
recurringDailyLabel.appendChild(recurringDailyInput);

// Create button to add new key-value pairs
const addKeyValueButton = document.createElement('button');
addKeyValueButton.innerText = 'Add Key-Value';
addKeyValueButton.style.marginTop = '10px';
addKeyValueButton.style.padding = '5px 10px';
addKeyValueButton.style.cursor = 'pointer';
addKeyValueButton.style.backgroundColor = '#4CAF50';
addKeyValueButton.style.color = '#ffffff';
addKeyValueButton.style.border = 'none';
addKeyValueButton.style.borderRadius = '5px';

addKeyValueButton.addEventListener('click', () => {
    const selectedProfile = localStorage.getItem('selectedProfile.notifier');
    const keyName = newKeyInput.value.trim();
    const valueText = newValueInput.value.trim();
    const dateTime = newDateTimeInput.value;
    const startTime = startTimeInput.value;
    const endTime = endTimeInput.value;
    const isRecurringDaily = recurringDailyInput.checked;
    if (selectedProfile && keyName && valueText && (dateTime || (startTime && endTime))) {
        let value = `<[Notifier] ${valueText}>`;
        if (dateTime) {
            value += ` ${dateTime}`;
        } else if (startTime && endTime) {
            value += ` ${startTime}-${endTime}`;
        }
        if (isRecurringDaily) {
            value += ' (Recurring Daily)';
        }
        const key = `${selectedProfile}.notifier:${keyName}`;
        localStorage.setItem(key, value);
        newKeyInput.value = '';
        newValueInput.value = '';
        newDateTimeInput.value = '';
        startTimeInput.value = '';
        endTimeInput.value = '';
        recurringDailyInput.checked = false;
        loadKeyValueEntries();
    }
});

keyValueContainer.appendChild(newKeyInput);
keyValueContainer.appendChild(newValueInput);
keyValueContainer.appendChild(newDateTimeInput);
keyValueContainer.appendChild(startTimeInput);
keyValueContainer.appendChild(endTimeInput);
keyValueContainer.appendChild(recurringDailyLabel);
keyValueContainer.appendChild(addKeyValueButton);
notifierPanel.appendChild(keyValueContainer);

// Load key-value pairs into the key-value list
function loadKeyValueEntries() {
    keyValueList.innerHTML = '';
    const selectedProfile = localStorage.getItem('selectedProfile.notifier');
    if (!selectedProfile) return;

    for (let i = 0; i < localStorage.length; i++) {
        const key = localStorage.key(i);
        if (key.startsWith(`${selectedProfile}.notifier:`)) {
            const value = localStorage.getItem(key);
            const keyValueItem = document.createElement('div');
            keyValueItem.style.display = 'flex';
            keyValueItem.style.justifyContent = 'space-between';
            keyValueItem.style.alignItems = 'center';
            keyValueItem.style.padding = '10px';
            keyValueItem.style.cursor = 'pointer';
            keyValueItem.style.backgroundColor = '#3F3F3F';
            keyValueItem.style.marginBottom = '5px';
            keyValueItem.style.borderRadius = '5px';

            const keySpan = document.createElement('span');
            keySpan.innerText = `${key.split(':')[1]}: ${value}`;
            keySpan.style.flex = '1';

            const deleteButton = document.createElement('button');
            deleteButton.innerText = 'x';
            deleteButton.style.marginLeft = '10px';
            deleteButton.style.padding = '2px 5px';
            deleteButton.style.backgroundColor = '#FF6347';
            deleteButton.style.color = '#ffffff';
            deleteButton.style.border = 'none';
            deleteButton.style.borderRadius = '3px';
            deleteButton.style.cursor = 'pointer';

            deleteButton.addEventListener('click', () => {
                localStorage.removeItem(key);
                loadKeyValueEntries();
            });

            keyValueItem.appendChild(keySpan);
            keyValueItem.appendChild(deleteButton);
            keyValueList.appendChild(keyValueItem);
        }
    }
}

// Load profiles into the profiles list
function loadProfileEntries() {
    profilesList.innerHTML = '';
    for (let i = 0; i < localStorage.length; i++) {
        const key = localStorage.key(i);
        if (key.startsWith('notifier.profile:')) {
            const profileName = key.split(':')[1];
            const profileItem = document.createElement('div');
            profileItem.style.display = 'flex';
            profileItem.style.justifyContent = 'space-between';
            profileItem.style.alignItems = 'center';
            profileItem.style.padding = '10px';
            profileItem.style.cursor = 'pointer';
            profileItem.style.backgroundColor = '#3F3F3F';
            profileItem.style.marginBottom = '5px';
            profileItem.style.borderRadius = '5px';

            const profileNameSpan = document.createElement('span');
            profileNameSpan.innerText = profileName;
            profileNameSpan.style.flex = '1';
            profileNameSpan.addEventListener('click', () => {
                localStorage.setItem('selectedProfile.notifier', profileName);
                highlightSelectedProfile(profileItem);
                loadKeyValueEntries();
            });

            const deleteButton = document.createElement('button');
            deleteButton.innerText = 'x';
            deleteButton.style.marginLeft = '10px';
            deleteButton.style.padding = '2px 5px';
            deleteButton.style.backgroundColor = '#FF6347';
            deleteButton.style.color = '#ffffff';
            deleteButton.style.border = 'none';
            deleteButton.style.borderRadius = '3px';
            deleteButton.style.cursor = 'pointer';

            deleteButton.addEventListener('click', () => {
                localStorage.removeItem(key);
                if (localStorage.getItem('selectedProfile.notifier') === profileName) {
                    localStorage.removeItem('selectedProfile.notifier');
                }
                loadProfileEntries();
                loadKeyValueEntries();
            });

            profileItem.appendChild(profileNameSpan);
            profileItem.appendChild(deleteButton);
            profilesList.appendChild(profileItem);
        }
    }
    highlightSelectedProfile();
}

// Highlight the selected profile
function highlightSelectedProfile(selectedItem = null) {
    const selectedProfile = localStorage.getItem('selectedProfile.notifier');
    Array.from(profilesList.children).forEach(profileItem => {
        if (selectedProfile && profileItem.children[0].innerText === selectedProfile) {
            profileItem.style.backgroundColor = '#4CAF50';
        } else {
            profileItem.style.backgroundColor = '#3F3F3F';
        }
    });

    if (selectedItem) {
        selectedItem.style.backgroundColor = '#4CAF50';
    }
}

// Append close button to the main panel
document.body.appendChild(notifierPanel);
notifierPanel.appendChild(closeButton);



let messageSentTimestamps = {}; // Store timestamps of sent messages

function setInputValue() {
    const inputElement = document.querySelector('[data-slate-editor="true"]') || document.querySelector('textarea[class*="textArea_"]');

    if (inputElement) {
        notifierActive = true; // Set notifier active to true

        // Get the selected profile from localStorage
        const selectedProfile = localStorage.getItem('selectedProfile.notifier');

        if (!selectedProfile) {
            console.error("Selected profile not found in localStorage");
            return;
        }

        // Retrieve messageSentTimestamps from localStorage to keep track of sent messages
        messageSentTimestamps = JSON.parse(localStorage.getItem('messageSentTimestamps') || '{}');

        // Find a notifier message key that starts with `${selectedProfile}.notifier:`
        let notifierMessage = null;
        let messageKey = null;
        let timeframe = null;
        let isTriggeredByTimeframe = false;

        for (let i = 0; i < localStorage.length; i++) {
            const key = localStorage.key(i);
            if (key.startsWith(`${selectedProfile}.notifier:`)) {
                const storedValue = localStorage.getItem(key);
                const dateTimeMatches = storedValue.match(/^<\[Notifier\]\s+(.+)>\s+(\d{4}-\d{2}-\d{2}T\d{2}:\d{2})(\s+\(Recurring Daily\))?$/);
                const timeframeMatches = storedValue.match(/^<\[Notifier\]\s+(.+)>\s+(\d{2}:\d{2}-\d{2}:\d{2})$/);

                const now = new Date();

                if (dateTimeMatches) {
                    // Handle exact date-time based messages
                    const message = dateTimeMatches[1]; // Full message content inside <>
                    const dateTimeInfo = dateTimeMatches[2];
                    const isRecurring = !!dateTimeMatches[3];
                    const dateTime = new Date(dateTimeInfo);

                    // Create a key to track if this message has been sent today
                    const sentTodayKey = `${key}-${now.toDateString()}`;

                    if (isRecurring) {
                        // Check only the time for recurring messages
                        if (dateTime.getHours() === now.getHours() && dateTime.getMinutes() === now.getMinutes() && !messageSentTimestamps[sentTodayKey]) {
                            notifierMessage = `<[Notifier] ${message}>`; // Ensure the entire message is used
                            messageKey = sentTodayKey;
                            break; // Exit loop after finding the first match
                        }
                    } else {
                        // Check both date and time for one-time messages
                        if (dateTime.toDateString() === now.toDateString() && dateTime.getHours() === now.getHours() && dateTime.getMinutes() === now.getMinutes() && !messageSentTimestamps[sentTodayKey]) {
                            notifierMessage = `<[Notifier] ${message}>`; // Ensure the entire message is used
                            messageKey = sentTodayKey;
                            break; // Exit loop after finding the first match
                        }
                    }
                } else if (timeframeMatches) {
                    // Handle timeframe-based messages
                    const message = timeframeMatches[1]; // Full message content inside <>
                    timeframe = timeframeMatches[2];

                    const [startTime, endTime] = timeframe.split('-').map(time => {
                        const [hours, minutes] = time.split(':').map(Number);
                        return { hours, minutes };
                    });

                    const currentHour = now.getHours();
                    const currentMinutes = now.getMinutes();

                    // Create a key to track if this message has been sent today
                    const sentTodayKey = `${key}-${now.toDateString()}`;

                    // Check if the current time falls within the specified timeframe
                    const isWithinTimeframe = (
                        (currentHour > startTime.hours || (currentHour === startTime.hours && currentMinutes >= startTime.minutes)) &&
                        (currentHour < endTime.hours || (currentHour === endTime.hours && currentMinutes <= endTime.minutes))
                    );

                    if (isWithinTimeframe && !messageSentTimestamps[sentTodayKey]) {
                        // Calculate the total number of minutes in the range
                        const startMinutes = startTime.hours * 60 + startTime.minutes;
                        const endMinutes = endTime.hours * 60 + endTime.minutes;
                        const totalMinutesInRange = endMinutes - startMinutes;

                        // Generate a random minute within the range
                        let randomMinuteInRange = startMinutes + Math.floor(Math.random() * totalMinutesInRange);

                        // Convert the random minute back to hours and minutes
                        let randomHour = Math.floor(randomMinuteInRange / 60);
                        let randomMinute = randomMinuteInRange % 60;

                        // Check if the current time matches the randomly chosen minute
                        if (currentHour === randomHour && currentMinutes === randomMinute) {
                            notifierMessage = `<[Notifier] ${message}>`; // Ensure the entire message is used
                            messageKey = sentTodayKey;
                            isTriggeredByTimeframe = true;
                            break;
                        }
                    }
                }
            }
        }

        if (!notifierMessage) {
            notifierActive = false; // Reset notifierActive to avoid interference
            return;
        }

        inputElement.focus();

        // Prevent the same message from being sent multiple times in the same minute
        const lastSentTime = messageSentTimestamps[messageKey];
        const now = new Date();
        if (lastSentTime && (now - new Date(lastSentTime)) < 60000) {
            console.log("Message already sent recently, skipping");
            notifierActive = false; // Reset notifierActive to avoid interference
            return;
        }

        if (inputElement.getAttribute('data-slate-editor') === 'true') {
            const inputEvent = new InputEvent('beforeinput', {
                bubbles: true,
                cancelable: true,
                inputType: 'insertText',
                data: `${notifierMessage}`, // Use the full notifier message from localStorage
            });
            inputElement.dispatchEvent(inputEvent);
        } else {
            // For mobile version, we need to activate the textarea properly
            const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, 'value').set;
            nativeInputValueSetter.call(inputElement, inputElement.value + notifierMessage);

            const inputEvent = new Event('input', {
                bubbles: true,
                cancelable: true,
            });
            inputElement.dispatchEvent(inputEvent);

            // Manually set the caret position to make it appear as though the user is interacting
            inputElement.setSelectionRange(inputElement.value.length, inputElement.value.length);
        }

        // Automatically send the message
        sendNotifierMessage(inputElement);
        notifierActive = false;

        // Record the timestamp of the sent message in both memory and localStorage
        messageSentTimestamps[messageKey] = now.toISOString();
        localStorage.setItem('messageSentTimestamps', JSON.stringify(messageSentTimestamps));
    }
}



function sendNotifierMessage(inputElement) {
    notifierActive = true;

    let sendButton = document.querySelector('button[aria-label="Nachricht senden"]');
    if (sendButton) {
        sendButton.click();
        console.log('Send button clicked to send message');
        notifierActive = false; // Reset notifierActive after sending
    } else {
        // For desktop version, simulate pressing Enter to send the message
        let enterEvent = new KeyboardEvent('keydown', {
            key: 'Enter',
            code: 'Enter',
            keyCode: 13,
            which: 13,
            bubbles: true,
            cancelable: true
        });
        inputElement.dispatchEvent(enterEvent);
        console.log('Enter key simulated to send message');
        notifierActive = false; // Reset notifierActive after sending
    }
}

function checkForMessages() {
    setInterval(() => {
        setInputValue();
    }, 20000); // Check every 20 seconds
}

const observer = new MutationObserver(() => {
    if (document.querySelector('[data-slate-editor="true"]') || document.querySelector('textarea[class*="textArea_"]')) {
        setInputValue();
    }
});

observer.observe(document.body, { childList: true, subtree: true });

checkForMessages();

}


// ================================================================= MAIN LOGIC =================================================================
function MainLogicScript() {
    // Function to check localStorage and reload if not ready
    function checkLocalStorageAndReload() {
        try {
            if (localStorage.length > 0) {
                console.log("LocalStorage has items. Proceeding with script...");
                initializeScript();
            } else {
                console.warn("LocalStorage is empty. Reloading page...");
                setTimeout(() => {
                    location.reload();
                }, 5000); // Wait 5 seconds before reloading
            }
        } catch (error) {
            console.error("Error accessing localStorage:", error);
            setTimeout(() => {
                location.reload();
            }, 5000); // Wait 5 seconds before reloading
        }
    }

    // Initial check for localStorage existence
    checkLocalStorageAndReload();

    function initializeScript() {
        // Retrieve settings from localStorage or set default values
        let enterKeyDisabled = JSON.parse(localStorage.getItem('enterKeyDisabled')) || false;
        let customRuleEnabled = JSON.parse(localStorage.getItem('customRuleEnabled')) || true;
        let scanForKeywordsEnabled = JSON.parse(localStorage.getItem('scanForKeywordsEnabled')) || true;

        // Create the settings window
window.settingsWindow = document.createElement('div');
settingsWindow.style.bottom = '60px';
settingsWindow.style.right = '20px';
settingsWindow.style.width = '250px';
settingsWindow.style.padding = '15px';
settingsWindow.style.color = 'white';
settingsWindow.style.borderRadius = '5px';
settingsWindow.style.zIndex = '1001';

// Custom Rule Checkbox
const enableCustomRuleCheckbox = document.createElement('input');
enableCustomRuleCheckbox.type = 'checkbox';
enableCustomRuleCheckbox.checked = customRuleEnabled;
enableCustomRuleCheckbox.id = 'enableCustomRuleCheckbox';

const enableCustomRuleLabel = document.createElement('label');
enableCustomRuleLabel.htmlFor = 'enableCustomRuleCheckbox';
enableCustomRuleLabel.innerText = ' Enable Custom Rules';
enableCustomRuleLabel.style.color = '#b0b0b0';

// Wrap Custom Rule elements in a div
const customRuleDiv = document.createElement('div');
customRuleDiv.style.marginBottom = '10px'; // Add spacing
customRuleDiv.appendChild(enableCustomRuleCheckbox);
customRuleDiv.appendChild(enableCustomRuleLabel);

// Scan for Keywords Checkbox
const enableScanForKeywordsCheckbox = document.createElement('input');
enableScanForKeywordsCheckbox.type = 'checkbox';
enableScanForKeywordsCheckbox.checked = scanForKeywordsEnabled;
enableScanForKeywordsCheckbox.id = 'enableScanForKeywordsCheckbox';

const enableScanForKeywordsLabel = document.createElement('label');
enableScanForKeywordsLabel.htmlFor = 'enableScanForKeywordsCheckbox';
enableScanForKeywordsLabel.innerText = ' Enable Lorebook';
enableScanForKeywordsLabel.style.color = '#b0b0b0';

// Wrap Scan for Keywords elements in a div
const scanForKeywordsDiv = document.createElement('div');
scanForKeywordsDiv.style.marginBottom = '10px'; // Add spacing
scanForKeywordsDiv.appendChild(enableScanForKeywordsCheckbox);
scanForKeywordsDiv.appendChild(enableScanForKeywordsLabel);

// Append elements to settings window
settingsWindow.appendChild(customRuleDiv);
settingsWindow.appendChild(scanForKeywordsDiv);


// Update customRuleEnabled when checkbox is toggled, and save it in localStorage
enableCustomRuleCheckbox.addEventListener('change', function() {
    customRuleEnabled = enableCustomRuleCheckbox.checked;
    localStorage.setItem('customRuleEnabled', JSON.stringify(customRuleEnabled));
});

// Update scanForKeywordsEnabled when checkbox is toggled, and save it in localStorage
enableScanForKeywordsCheckbox.addEventListener('change', function() {
    scanForKeywordsEnabled = enableScanForKeywordsCheckbox.checked;
    localStorage.setItem('scanForKeywordsEnabled', JSON.stringify(scanForKeywordsEnabled));
});


// Function to get the correct input element based on the mode
function getInputElement() {
    return document.querySelector('[data-slate-editor="true"]') || document.querySelector('textarea[class*="textArea_"]');
}

// Add event listener to handle Enter key behavior
window.addEventListener('keydown', function(event) {
    if (notifierActive) return;

    const inputElement = getInputElement();
    if (event.key === 'Enter' && !event.shiftKey && !enterKeyDisabled) {
        if (inputElement && inputElement.nodeName === 'TEXTAREA') {
            return;
        }

        event.preventDefault();
        event.stopPropagation();
        event.stopImmediatePropagation();
        console.log('Enter key disabled');
        enterKeyDisabled = true;

        handleEnterKey();

        enterKeyDisabled = false;
    }
}, true);


// Add event listener to the send button to execute handleEnterKey when clicked
window.addEventListener('click', function(event) {
    if (notifierActive) {
        return; // Skip handling if the notifier is active
    }
    const sendButton = document.querySelector('button[aria-label="Nachricht senden"]');
    const inputElement = getInputElement();

    if (sendButton && sendButton.contains(event.target)) {
        if (inputElement && inputElement.nodeName === 'TEXTAREA') {
            // Skip handleEnterKey() if notifier is active
            if (!notifierActive) {
                handleEnterKey();
            }
        }
    }
}, true);



// Main function that handles Enter key behavior
function handleEnterKey() {
    if (notifierActive) {
        console.log('Notifier is active, skipping handleEnterKey');
        return; // Prevent handleEnterKey from executing if notifier is active
    }

    let inputElement = getInputElement();
    if (inputElement) {
        inputElement.focus();
        setCursorToEnd(inputElement);
        if (customRuleEnabled) {
            applyCustomRule(inputElement);
        }
        setCursorToEnd(inputElement);
        if (scanForKeywordsEnabled) {
            scanForKeywords(inputElement);
        }
        getRandomEntry(inputElement);
        sendMessage(inputElement);
        anotherCustomFunction();
    }
}


// Function to apply custom rules for the input field
function applyCustomRule(inputElement) {
    const customRule = window.customRuleLogic ? window.customRuleLogic.getCurrentText() : '';

    if (inputElement.nodeName === 'TEXTAREA') {
        // For mobile version where input is <textarea>
        const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, 'value').set;
        nativeInputValueSetter.call(inputElement, inputElement.value + customRule);

        const inputEvent = new Event('input', {
            bubbles: true,
            cancelable: true,
        });
        inputElement.dispatchEvent(inputEvent);
    } else {
        // For desktop version where input is a Slate editor
        const inputEvent = new InputEvent('beforeinput', {
            bubbles: true,
            cancelable: true,
            inputType: 'insertText',
            data: customRule,
        });
        inputElement.dispatchEvent(inputEvent);
    }
}

// Function to set the cursor position to the end after inserting the text
function setCursorToEnd(inputElement) {
    if (inputElement.nodeName === 'TEXTAREA') {
        // For mobile version where input is <textarea>
        inputElement.selectionStart = inputElement.selectionEnd = inputElement.value.length;
    } else {
        // For desktop version where input is a Slate editor
        inputElement.focus();

        // Simulate repeated Ctrl + ArrowRight key press events to move cursor to the end
        const repeatPresses = 150; // Number of times to simulate Ctrl + ArrowRight
        for (let i = 0; i < repeatPresses; i++) {
            const ctrlArrowRightEvent = new KeyboardEvent('keydown', {
                key: 'ArrowRight',
                code: 'ArrowRight',
                keyCode: 39, // ArrowRight key code
                charCode: 0,
                which: 39,
                bubbles: true,
                cancelable: true,
                ctrlKey: true // Set Ctrl key to true
            });
            inputElement.dispatchEvent(ctrlArrowRightEvent);
        }
    }
}

// Function to send the message (either click send button or simulate Enter key)
function sendMessage(inputElement) {
    if (inputElement.nodeName === 'TEXTAREA') {
        // Mobile version: Do not send message, just return to allow linebreak
        return;
    }

    let sendButton = document.querySelector('button[aria-label="Nachricht senden"]');
    if (sendButton) {
        sendButton.click();
        console.log('Send button clicked to send message');
    } else {
        // For desktop version, simulate pressing Enter to send the message
        let enterEvent = new KeyboardEvent('keydown', {
            key: 'Enter',
            code: 'Enter',
            keyCode: 13,
            which: 13,
            bubbles: true,
            cancelable: true
        });
        inputElement.dispatchEvent(enterEvent);
        console.log('Enter key simulated to send message');
    }
}



// Example of adding another function
function anotherCustomFunction() {
    console.log('Another custom function executed');
}




// Function to get the current profile from local storage
function getCurrentProfile() {
    return localStorage.getItem('selectedProfile.lorebook');
}



// Function to scan for keywords and access local storage
function scanForKeywords(inputElement) {
    const currentProfile = getCurrentProfile();
    if (currentProfile) {
        // Retrieve all messages before iterating through storage keys
        const messageItems = document.querySelectorAll('div[class*="messageContent_"]');
        let relevantMessages = Array.from(messageItems).slice(-15); // Last 15 messages
        const lastMessage = Array.from(messageItems).slice(-1); // Last message only


// Iterate over the last 15 messages to extract hidden bracket content
relevantMessages = relevantMessages.map(msg => {
    // Retrieve all span elements within the message
    const spans = msg.querySelectorAll('span');

    // Filter out the spans based on both style conditions: opacity and position
    const hiddenSpans = Array.from(spans).filter(span => {
        const style = window.getComputedStyle(span);
        return style.opacity === '0' && style.position === 'absolute';
    });

    // Join the text content of all matching spans, converting them to lowercase
    const bracketContent = hiddenSpans.map(span => span.textContent.toLowerCase()).join('');

    // Extract content within square brackets, if any
    const match = bracketContent.match(/\[(.*?)\]/);
    return match ? match[1] : null;
}).filter(content => content !== null);

// Log the filtered messages for debugging purposes
console.log("Filtered Relevant Messages (content in brackets, last 15):", relevantMessages);
        console.log("Last Message:", lastMessage.map(msg => msg.textContent));

        // Track how many entries have been appended
        let appendedCount = 0;
        const maxAppends = 3;

        // Check if the last message contains a specific link pattern
        const mp3LinkPattern = /https:\/\/files\.shapes\.inc\/.*\.mp3/;
        let mp3LinkValue = null;

        if (lastMessage.length > 0) {
        const lastMessageText = lastMessage[0].textContent.toLowerCase();

            const mp3LinkMatch = lastMessageText.match(mp3LinkPattern);
            if (mp3LinkMatch) {
                const mp3LinkKey = mp3LinkMatch[0];
                mp3LinkValue = localStorage.getItem(mp3LinkKey);
                console.log(`MP3 Link detected: ${mp3LinkKey}. Retrieved value: ${mp3LinkValue}`);
            }
        }

        // Create an array to hold all entry keys that need to be checked
        let allEntryKeys = [];

        // Iterate through all localStorage keys that match the profile-lorebook prefix
        Object.keys(localStorage).forEach(storageKey => {
            if (storageKey.startsWith(`${currentProfile}.lorebook:`)) {
                const entryKeys = storageKey.replace(`${currentProfile}.lorebook:`, '').split(',');
                const entryValue = localStorage.getItem(storageKey);

                // Log the entry keys for debugging purposes
                console.log(`Entry Keys: `, entryKeys);

                entryKeys.forEach(entryKey => {
                    allEntryKeys.push({ entryKey, entryValue });
                });
            }
        });

        // If mp3LinkValue is present, parse it for keywords as well
        if (mp3LinkValue) {
            console.log(`Scanning MP3 link value for keywords: ${mp3LinkValue}`);
            const mp3Keywords = mp3LinkValue.split(',');
            mp3Keywords.forEach(keyword => {
                const trimmedKeyword = keyword.trim();
                console.log(`Adding keyword from MP3 value: ${trimmedKeyword}`);
                // Add mp3 keywords but set entryValue to an empty string instead of null
                allEntryKeys.push({ entryKey: trimmedKeyword, entryValue: '' });
            });
        }

        // Iterate over all collected entry keys and perform the checks
        allEntryKeys.forEach(({ entryKey, entryValue }) => {
            if (appendedCount >= maxAppends) return; // Stop if max appends reached

            // Log each keyword being checked
            console.log(`Checking keyword: ${entryKey}`);

            // Check input element text for complete word match of keyword (case-insensitive)
            const inputText = inputElement.value || inputElement.textContent;

            // Combine check for keyword in input, in the last message, or in the mp3 link value
            const isKeywordInInput = inputText && new RegExp(`\\b${entryKey}\\b`, 'i').test(inputText);
            const isKeywordInLastMessage = lastMessage.some(message => {
                const lastMessageText = message.textContent;
                return new RegExp(`\\b${entryKey}\\b`, 'i').test(lastMessageText);
            });
            const isKeywordInMp3LinkValue = mp3LinkValue && mp3LinkValue.includes(entryKey);

            console.log(`Keyword '${entryKey}' in input: ${isKeywordInInput}, in last message: ${isKeywordInLastMessage}, in MP3 value: ${isKeywordInMp3LinkValue}`);

            if ((isKeywordInInput || isKeywordInLastMessage || isKeywordInMp3LinkValue) && entryValue) {
                const keywordAlreadyUsed = relevantMessages.some(bracketContent => {
                    return new RegExp(`\\b${entryKey}\\b`, 'i').test(bracketContent);
                });

                if (!keywordAlreadyUsed) {
                    // Append the entryValue to the input element only if entryValue is not null or empty
                    if (inputElement.nodeName === 'TEXTAREA') {
                        const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, 'value').set;
                        nativeInputValueSetter.call(inputElement, inputElement.value + '\n' + entryValue);

                        const inputEvent = new Event('input', {
                            bubbles: true,
                            cancelable: true,
                        });
                        inputElement.dispatchEvent(inputEvent);
                    } else {
                        const inputEvent = new InputEvent('beforeinput', {
                            bubbles: true,
                            cancelable: true,
                            inputType: 'insertText',
                            data: '\n' + entryValue,
                        });
                        inputElement.dispatchEvent(inputEvent);
                    }
                    appendedCount++; // Increment the count
                    console.log(`Keyword '${entryKey}' detected. Appended lorebook entry to the input.`);
                } else {
                    console.log(`Keyword '${entryKey}' already found in recent bracketed messages or entryValue is null/empty. Skipping append.`);
                }
            }
        });

        // Log the total number of entries appended
        console.log(`Total lorebook entries appended: ${appendedCount}`);
    }
}




function getRandomEntry(inputElement) {
    const selectedProfile = localStorage.getItem('selectedProfile.events');
    if (selectedProfile) {
        let profileEntries = [];
        const currentHour = new Date().getHours();
for (let key in localStorage) {
    if (key.startsWith(`${selectedProfile}.events:`)) {
        const entryData = JSON.parse(localStorage.getItem(key));
        const [startHour, endHour] = entryData.timeRange.split('-').map(Number);
        // Check if current hour is within the time range
        if (
            (startHour <= endHour && currentHour >= startHour && currentHour < endHour) || // Normal range
            (startHour > endHour && (currentHour >= startHour || currentHour < endHour)) // Crosses midnight
        ) {
            profileEntries.push({ key, ...entryData });
        }
    }
}

        if (profileEntries.length > 0) {
            const probability = parseInt(localStorage.getItem('events.probability') || '100', 10);
            let selectedEntry = null;
            while (profileEntries.length > 0) {
                // Randomly select an entry from the available entries
                const randomIndex = Math.floor(Math.random() * profileEntries.length);
                const randomEntry = profileEntries[randomIndex];
                // Check if the entry passes the individual probability check
                if (Math.random() * 100 < randomEntry.probability) {
                    selectedEntry = randomEntry;
                    break;
                } else {
                    // Remove the entry from the list if it fails the probability check
                    profileEntries.splice(randomIndex, 1);
                }
            }
            if (selectedEntry && Math.random() * 100 < probability) {
                console.log(`Random Entry Selected: ${selectedEntry.value}`);
                appendToInput(inputElement, selectedEntry.value); // Append the random entry to the input element
            }
        } else {
            console.log('No entries available for the selected profile in the current time range.');
        }
    } else {
        console.log('No profile selected. Please select a profile to retrieve a random entry.');
    }
}

// Helper function to append text to the input element
function appendToInput(inputElement, text) {
    const lineBreak = '\n';
    if (!inputElement) {
        console.error('Input element not found.');
        return;
    }

    if (inputElement.nodeName === 'TEXTAREA') {
        // Mobile: Append text to <textarea>
        const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, 'value').set;
        nativeInputValueSetter.call(inputElement, inputElement.value + `${lineBreak}${text}`);

        const inputEvent = new Event('input', {
            bubbles: true,
            cancelable: true,
        });
        inputElement.dispatchEvent(inputEvent);
    } else if (inputElement.hasAttribute('data-slate-editor')) {
        // Desktop: Append text for Slate editor
        const inputEvent = new InputEvent('beforeinput', {
            bubbles: true,
            cancelable: true,
            inputType: 'insertText',
            data: `${lineBreak}${text}`,
        });
        inputElement.dispatchEvent(inputEvent);
    } else {
        console.error('Unsupported input element type.');
    }
}



// Expose the function to be accessible from other scripts
window.getRandomEntry = getRandomEntry;


  }

}

// =================================================================== BUTTONS ==================================================================
function createDivider() {
const divider = document.createElement('div');
divider.style.height = '1px';
divider.style.backgroundColor = '#212121';
divider.style.margin = '20px 20px 0px 20px';
    return divider;
}


function createFooterText() {
    const footerText = document.createElement('div');
    footerText.textContent = '© Vishanka 2024';
    footerText.style.position = 'absolute';
    footerText.style.bottom = '10px';
    footerText.style.left = '50%';
    footerText.style.transform = 'translateX(-50%)';
    footerText.style.fontSize = '12px';
    footerText.style.fontWeight = '550';
    footerText.style.color = '#272727';
    return footerText;
}

function initializeButton() {
    DCstoragePanel.appendChild(openLorebookButton);


    DCstoragePanel.appendChild(eventsButton);


    DCstoragePanel.appendChild(manageRulesButton);
    DCstoragePanel.appendChild(notifierToggleButton);
    DCstoragePanel.appendChild(createDivider()); // Add divider after manageRulesButton

    DCstoragePanel.appendChild(serverbartoggleButton);


    DCstoragePanel.appendChild(mp3ToggleButton);
    DCstoragePanel.appendChild(createDivider()); // Add divider after mp3ToggleButton

    DCstoragePanel.appendChild(exportButton);

    DCstoragePanel.appendChild(importButton);
    DCstoragePanel.appendChild(createDivider()); // Add divider after importButton

    DCstoragePanel.appendChild(settingsWindow);

    DCstoragePanel.appendChild(createFooterText());
}


// ============================================================ SCRIPT LOADING ORDER ============================================================

LorebookScript();
ImportExportScript();
EventsScript();
RulesScript();
mp3Script();
StylesScript();
HiderScript();
MainLogicScript();
NotifierScript();
initializeButton();


})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址