⚒ BETA Wizardebop 3.00 ⚒

The Best Acellus.com Mod Menu

// ==UserScript==
// @name         ⚒ BETA Wizardebop 3.00 ⚒
// @author       Type Stuff
// @description  The Best Acellus.com Mod Menu
// @version      0.2
// @match        https://admin192a.acellus.com/student/*
// @match        https://admin192c.acellus.com/student/*
// @run-at       document-start
// @grant        none
// @namespace    https://greasyfork.dpdns.org/users/1394549
// @icon         https://img.freepik.com/free-vector/halloween-witch-hat-isolated-illustration_18591-83719.jpg
// @license      Proprietary — see below
// ==/UserScript==

/*
  © 2025 TypeStuff. All Rights Reserved.

  You are free to:
    • Install and run this script.
    • Modify the code for your own, personal, non-commercial use.

  You MAY NOT:
    • Redistribute, re-host, repost, or re-upload this script in any form.
    • Sell, license, or otherwise make available this script (original or modified).
*/

(function() {
  'use strict';

  /* -------------------
     0) AI CHATBOT INTEGRATION
     ------------------- */
  function setupAIChatbot() {
    const aiTab      = document.querySelector('.category-menu#ai');
    const container  = document.createElement('div');
    container.id     = 'ai-chatbot';
    container.style  = 'padding:8px;';
    container.innerHTML = `
      <div id="chat-container" style="display:flex;flex-direction:column;height:300px;">
        <div id="chat-messages" style="flex:1;overflow:auto;border:1px solid #ccc;padding:8px;background:#fff;border-radius:4px;margin-bottom:8px;"></div>
        <div style="display:flex;align-items:center;">
          <select id="template-select" class="wm-input" style="margin-right:8px;">
            <option value="">No template</option>
            <option value="essay">Essay Writer</option>
          </select>
          <input id="chat-input" type="text" class="wm-input" placeholder="Type your message..." style="flex:1;margin-right:8px;"/>
          <button id="chat-send" class="wm-button">Send</button>
        </div>
        <div id="chat-error" style="color:red;font-size:12px;margin-top:4px;display:none;"></div>
      </div>
    `;
    aiTab.appendChild(container);

    const AI_MAX          = 15;
    const AI_PROMPTS_KEY  = 'wizardebop-ai-prompts';
    const AI_TEMPLATE_KEY = 'wizardebop-ai-template';

    function getPromptTimestamps(){
      let arr = [];
      try { arr = JSON.parse(localStorage.getItem(AI_PROMPTS_KEY) || '[]'); }
      catch { arr = []; }
      return Array.isArray(arr) ? arr : [];
    }
    function savePromptTimestamps(arr){
      localStorage.setItem(AI_PROMPTS_KEY, JSON.stringify(arr));
    }
    function recordPrompt(){
      const now = Date.now();
      const oneHour = 60*60*1000;
      let arr = getPromptTimestamps().filter(ts => now - ts < oneHour);
      arr.push(now);
      savePromptTimestamps(arr);
      return arr.length;
    }
    function canSendPrompt(){
      const now = Date.now();
      const oneHour = 60*60*1000;
      return getPromptTimestamps().filter(ts => now - ts < oneHour).length < AI_MAX;
    }

async function fetchAI(messages) {
  const res = await fetch('http://localhost:11434', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      model: 'gemm3:1b',
      messages
    })
  });

  if (!res.ok) {
    throw new Error(`AI request failed: ${res.status} ${res.statusText}`);
  }

  const data = await res.json();
  return data.choices[0].message.content.trim();
}

    const tplSelect = document.getElementById('template-select');
    const inputEl   = document.getElementById('chat-input');
    const sendBtn   = document.getElementById('chat-send');
    const msgsDiv   = document.getElementById('chat-messages');
    const errDiv    = document.getElementById('chat-error');

    tplSelect.value = localStorage.getItem(AI_TEMPLATE_KEY) || '';

    sendBtn.addEventListener('click', async () => {
      errDiv.style.display = 'none';
      if (!canSendPrompt()) {
        errDiv.textContent = `Rate limit reached: ${AI_MAX} prompts per hour.`;
        errDiv.style.display = 'block';
        return;
      }
      const raw = inputEl.value.trim();
      if (!raw) return;
      const template = tplSelect.value;
      localStorage.setItem(AI_TEMPLATE_KEY, template);

      let messages = [];
      if (template === 'essay') {
        messages.push({
          role: 'system',
          content: 'Make a detailed 200-word essay that gets a 100%, and grammar is perfect and punctuation is also perfect, about:'
        });
      }
      messages.push({ role: 'user', content: raw });

      recordPrompt();
      if (!canSendPrompt()) sendBtn.disabled = true;

      msgsDiv.innerHTML += `<div><strong>You:</strong> ${raw}</div>`;
      msgsDiv.scrollTop = msgsDiv.scrollHeight;
      inputEl.value = '';

      try {
        const aiResp = await fetchAI(messages);
        msgsDiv.innerHTML += `<div><strong>AI:</strong> ${aiResp}</div>`;
        msgsDiv.scrollTop = msgsDiv.scrollHeight;

        if (template === 'essay') {
          const summary = await fetchAI([
            { role: 'assistant', content: aiResp },
            { role: 'user', content: 'Describe what the above essay is about in one sentence.' }
          ]);
          msgsDiv.innerHTML += `<div><em>Summary:</em> ${summary}</div>`;
          msgsDiv.scrollTop = msgsDiv.scrollHeight;
        }
      } catch (err) {
        errDiv.textContent = 'Error: ' + err.message;
        errDiv.style.display = 'block';
      }
    });
  }

  /* ------------------
     1) SETTINGS & STATE
     ------------------ */
  const STORAGE = {
    wallpaper:   'wizardebop-wallpaper',
    unpause:     'wizardebop-unpause',
    pasteFast:   'wizardebop-paste',
    autoSpeed:   'wizardebop-autoSpeed',
    btnBg:       'wizardebop-btn-bg',
    btnHover:    'wizardebop-btn-hover',
    btnRadius:   'wizardebop-btn-radius',
    btnFont:     'wizardebop-btn-font',
    btnPad:      'wizardebop-btn-pad',
    animDur:     'wizardebop-anim-duration',
    password:    'wizardebop-password',
    keybind:     'wizardebop-keybind',
    notes:       'wizardebop-notes',
    todos:       'wizardebop-todos',
    showTimer:   'wizardebop-show-timer'
  };

  let autoUnpause       = localStorage.getItem(STORAGE.unpause)   === 'true';
  let pasteFast         = localStorage.getItem(STORAGE.pasteFast) === 'true';
  let autoSpeed         = localStorage.getItem(STORAGE.autoSpeed) === 'true';
  let userPass          = localStorage.getItem(STORAGE.password)  || '';
  let toggleKey         = localStorage.getItem(STORAGE.keybind)   || 'F2';
  let savedNotes        = localStorage.getItem(STORAGE.notes)     || '';
  let todoList          = JSON.parse(localStorage.getItem(STORAGE.todos) || '[]');
  let showTimerOnScreen = localStorage.getItem(STORAGE.showTimer) === 'true';

  const BTN = {
    bg:     localStorage.getItem(STORAGE.btnBg)     || 'rgba(128,128,128,0.5)',
    hover:  localStorage.getItem(STORAGE.btnHover)  || 'rgba(255,255,255,0.3)',
    radius: localStorage.getItem(STORAGE.btnRadius) || '6px',
    font:   localStorage.getItem(STORAGE.btnFont)   || '14px',
    pad:    localStorage.getItem(STORAGE.btnPad)    || '6px 12px'
  };
  const ANIM = {
    gradDur: +localStorage.getItem(STORAGE.animDur) || 12
  };

  let timerInterval = null,
      timerElapsed  = 0;
  let pomoInterval   = null,
      pomoRemaining  = 25 * 60,
      pomoPhase      = 'work',
      pomoCycleCount = 0;

  function save(k,v){ localStorage.setItem(k,v); }
  function saveTodos(){ save(STORAGE.todos, JSON.stringify(todoList)); }

  /* -------------------
     2) AUTO-UNPAUSE
     ------------------- */
  function enableUnpause(){
    Object.defineProperty(document,'hidden',{get:()=>false});
    Object.defineProperty(document,'visibilityState',{get:()=> 'visible'});
    document.addEventListener('visibilitychange',e=>e.stopImmediatePropagation(),true);
  }
  if(autoUnpause) enableUnpause();
  new MutationObserver(()=>{ if(autoUnpause) enableUnpause(); })
    .observe(document,{childList:true,subtree:true});

  /* -------------------
     3) WALLPAPER HELPERS
     ------------------- */
  function loadWP(){
    try{ return JSON.parse(localStorage.getItem(STORAGE.wallpaper)); }
    catch{ return null; }
  }
  function saveWP(type,val){
    localStorage.setItem(STORAGE.wallpaper, JSON.stringify({type,val}));
  }
  function createWP(){
    let el = document.getElementById('global-wallpaper');
    if(!el){
      el = document.createElement('div');
      el.id = 'global-wallpaper';
      document.body.prepend(el);
    }
    return el;
  }
  function changeWP(type,val,saveFlag=true){
    const w = createWP();
    Object.assign(w.style,{
      position:'fixed', top:'0', left:'0',
      width:'100vw', height:'100vh',
      zIndex:'-1', pointerEvents:'none', animation:''
    });
    if(type==='gradient'){
      w.style.background = 'linear-gradient(135deg,rgba(255,182,193,0.6),rgba(176,224,230,0.6),rgba(221,160,221,0.6),rgba(255,228,181,0.6))';
      w.style.backgroundSize = '200% 200%';
      w.style.animation = `pastelGradient ${ANIM.gradDur}s ease infinite`;
    } else if(type.startsWith('ai_')){
      const topic = type.split('_')[1];
      w.style.background = `url('https://source.unsplash.com/1600x900/?ai-art,${topic}') no-repeat center/cover`;
    } else if(type==='custom'){
      w.style.background = val;
    } else if(type==='upload'){
      w.style.background = `url('${val}') no-repeat center/cover`;
    }
    if(saveFlag) saveWP(type,val);
  }

  /* -------------------
     4) ESSAY PASTER GUI
     ------------------- */
  function setupPaste(){
    let last = null;
    const overlay = document.createElement('div');
    overlay.id = 'pasteOverlay';
    overlay.style.cssText =
      'position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);' +
      'background:rgba(0,0,0,0.7);padding:20px;border-radius:8px;z-index:10003;display:none';
    overlay.innerHTML =
      `<div style="display:flex;flex-direction:column;gap:10px;">
         <h3 style="margin:0;color:#000">✎ Paste Anything</h3>
         <textarea id="pasteText"
           style="width:300px;height:100px;padding:8px;border-radius:4px;border:none;color:#000">
         </textarea>
       </div>
       <div style="display:flex;gap:8px;margin-top:10px;">
         <button id="pasteNow"
           style="padding:6px;border:none;border-radius:4px;cursor:pointer;background:${BTN.bg};transition:background 0.3s;">
           Paste
         </button>
         <button id="closePaste"
           style="padding:6px;border:none;border-radius:4px;cursor:pointer;background:${BTN.bg};transition:background 0.3s;">
           Close
         </button>
         <button id="speedButton"
           style="padding:6px;border:none;border-radius:4px;cursor:pointer;background:${BTN.bg};transition:background 0.3s;">
           ${autoSpeed ? '1.5× Auto ON' : '1.5× Now'}
         </button>
       </div>`;
    document.body.appendChild(overlay);

    overlay.querySelector('#pasteNow').addEventListener('click', ()=>{
      const txt = overlay.querySelector('#pasteText').value;
      if(last){
        last.focus();
        let i=0;
        const ev = new Event('input',{bubbles:true});
        const iv = setInterval(()=>{
          if(last.isContentEditable) last.textContent += txt[i];
          else last.value += txt[i];
          last.dispatchEvent(ev);
          if(++i >= txt.length) clearInterval(iv);
        },5);
      }
      overlay.style.display = 'none';
    });

    overlay.querySelector('#closePaste').addEventListener('click', ()=>{
      overlay.style.display = 'none';
    });

    const speedBtn = overlay.querySelector('#speedButton');
    speedBtn.addEventListener('click', ()=>{
      document.querySelectorAll('video').forEach(v=> v.playbackRate = 1.5);
    });
    speedBtn.addEventListener('contextmenu', e=>{
      e.preventDefault();
      autoSpeed = !autoSpeed;
      save(STORAGE.autoSpeed, autoSpeed);
      speedBtn.textContent = autoSpeed ? '1.5× Auto ON' : '1.5× Now';
      if(autoSpeed) applyAutoSpeed();
    });

    document.addEventListener('click', e=>{
      if(!pasteFast) return;
      const t = e.target;
      if(document.getElementById('settings-menu')?.contains(t)) return;
      if(overlay.contains(t)) return;
      if(t.isContentEditable || t.nodeName==='TEXTAREA' || (t.nodeName==='INPUT'&&t.type==='text')){
        last = t;
        overlay.style.display = 'block';
      }
    }, true);
  }

  /* -------------------
     5) STYLE INJECTION
     ------------------- */
  const styleEl = document.createElement('style');
  styleEl.textContent = `
    @keyframes pastelGradient {
      0% { background-position:0% 0% }
      50% { background-position:100% 100% }
      100% { background-position:0% 0% }
    }

    #settings-overlay {
      position:fixed;top:0;left:0;width:100vw;height:100vh;
      background:rgba(0,0,0,0.2);backdrop-filter:blur(4px);z-index:10000;
      display:none;
    }
    #settings-menu {
      position:fixed;top:50%;left:50%;
      transform:translate(-50%,-50%) scale(0.8);
      width:760px;height:420px;
      background:rgba(255,255,255,0.8);
      backdrop-filter:blur(6px);
      border-radius:12px;
      box-shadow:0 0 20px rgba(0,0,0,0.5);
      display:none;flex-direction:row;
      z-index:10001;opacity:0;
      transition:opacity 0.3s ease,transform 0.3s ease;
    }
    #settings-menu.visible {
      display:flex;opacity:1;
      transform:translate(-50%,-50%) scale(1);
    }
    #settings-button {
      position:fixed;bottom:20px;right:20px;
      background:rgba(128,128,128,0.5);
      color:#000;border:none;border-radius:6px;
      padding:6px;font-size:18px;cursor:pointer;
      z-index:10002;backdrop-filter:blur(4px);
      transition:transform 0.2s;
    }
    #settings-button:hover { transform:scale(1.1) }
    .settings-categories {
      width:20%;background:rgba(0,0,0,0.1);
      display:flex;flex-direction:column;
      padding:10px;overflow-y:auto;
    }
    .settings-categories button {
      background:rgba(255,255,255,0.5);
      color:#000;border:none;margin:4px 0;
      padding:6px;border-radius:6px;
      cursor:pointer;transition:background 0.3s,transform 0.2s;
      text-align:left;font-size:14px;
    }
    .settings-categories button:hover {
      background:rgba(200,200,200,0.6);
      transform:translateX(4px);
    }
    .settings-categories button.active {
      background:rgba(200,200,200,0.8);color:#000;
    }
    .settings-details {
      width:80%;padding:20px;overflow-y:auto;color:#000;
      position:relative;
    }
    .category-menu { display:none }
    .category-menu.active { display:block }
    .category-menu#timer {
      background:rgba(200,200,200,0.1);
      border-radius:6px; padding:10px;
    }
    .category-menu h3 { margin-top:0;font-size:18px }
    .category-menu h4 { margin:12px 0 4px;font-size:16px }
    .category-menu label { display:block;margin:8px 0;font-size:14px }
    .category-menu input.wm-input {
      width:90%;margin:4px 0;padding:4px;
      border-radius:4px;border:1px solid #ccc;
    }
    button.wm-button {
      margin:6px 4px;padding:${BTN.pad};
      background:${BTN.bg};border:none;
      border-radius:${BTN.radius};
      font-size:${BTN.font};cursor:pointer;
      transition:background 0.3s;
    }
    button.wm-button:hover { background:${BTN.hover} }
    #close-x {
      position:absolute;top:8px;right:8px;
      background:transparent;border:none;
      font-size:20px;cursor:pointer;
    }
    #screen-timer {
      position:absolute;top:100px;left:100px;
      background:rgba(0,0,0,0.7);color:#fff;
      padding:8px 12px;border-radius:4px;
      font-size:16px;cursor:move;
      z-index:10005;display:none;user-select:none;
    }
  `;
  document.head.appendChild(styleEl);

  /* -------------------
     6) CREATE ON-SCREEN TIMER
     -------------------
  */
  let screenTimerEl;
  function createScreenTimer(){
    if(screenTimerEl) return;
    screenTimerEl = document.createElement('div');
    screenTimerEl.id = 'screen-timer';
    screenTimerEl.textContent = '00:00:00';
    document.body.appendChild(screenTimerEl);
    let dragging=false, ox=0, oy=0;
    screenTimerEl.addEventListener('mousedown', e=>{
      dragging=true;
      ox = e.clientX - screenTimerEl.offsetLeft;
      oy = e.clientY - screenTimerEl.offsetTop;
      e.preventDefault();
    });
    document.addEventListener('mousemove', e=>{
      if(dragging){
        screenTimerEl.style.left = `${e.clientX - ox}px`;
        screenTimerEl.style.top  = `${e.clientY - oy}px`;
      }
    });
    document.addEventListener('mouseup', ()=>dragging=false);
    screenTimerEl.style.display = showTimerOnScreen ? 'block' : 'none';
  }

  /* -------------------
     7) AUTO-SPEED LOGIC
     -------------------
  */
  function applyAutoSpeed(){
    const setAll = ()=> document.querySelectorAll('video').forEach(v=> v.playbackRate = 1.5);
    setAll();
    new MutationObserver(setAll)
      .observe(document.body, { childList: true, subtree: true });
    document.addEventListener('play', e=>{
      if(e.target.tagName === 'VIDEO')
        e.target.playbackRate = 1.5;
    }, true);
  }

  /* -------------------
     8) BUILD SETTINGS MENU
     -------------------
  */
  function buildMenu(){
    const overlay = document.createElement('div');
    overlay.id = 'settings-overlay';
    document.body.appendChild(overlay);

    const btn = document.createElement('button');
    btn.id = 'settings-button';
    btn.textContent = '⚙️';
    document.body.appendChild(btn);

    const menu = document.createElement('div');
    menu.id = 'settings-menu';
    menu.innerHTML =
      `<button id='close-x'>×</button>` +
      `<div class='settings-categories'>` +
        `<button class='cat-btn active' data-cat='general'>General</button>` +
        `<button class='cat-btn' data-cat='ai'>AI</button>` +
        `<button class='cat-btn' data-cat='wallpaper'>Wallpaper</button>` +
        `<button class='cat-btn' data-cat='buttons'>Buttons</button>` +
        `<button class='cat-btn' data-cat='animations'>Animations</button>` +
        `<button class='cat-btn' data-cat='notes'>Notes</button>` +
        `<button class='cat-btn' data-cat='todo'>To-Do</button>` +
        `<button class='cat-btn' data-cat='timer'>Timer</button>` +
        `<button class='cat-btn' data-cat='extras'>Extras</button>` +
      `</div>` +
      `<div class='settings-details'>` +

        `<div class='category-menu active' id='general'>` +
          `<h3>General</h3>` +
          `<label><input type='checkbox' id='chk-unpause' ${autoUnpause?'checked':''}/> Auto-Unpause</label>` +
          `<label><input type='checkbox' id='chk-paste'   ${pasteFast?'checked':''}/> Essay Paster</label>` +
          `<label><input type='checkbox' id='chk-speed'   ${autoSpeed?'checked':''}/> Auto 1.5× Video</label>` +
          `<label>Password: <input type='password' id='menu-pass' class='wm-input' value='${userPass}'></label>` +
          `<label>Keybind: <button id='keybind-btn' class='wm-button'>${toggleKey===' ' ? 'Space' : toggleKey}</button></label>` +
          `<button id='apply-general' class='wm-button'>Apply</button>` +
        `</div>` +

        `<div class='category-menu' id='ai'>` +
          `<h3>AI</h3>` +
          `<div id='ai-settings' style='padding:4px 0;color:#555;'></div>` +
        `</div>` +

        `<div class='category-menu' id='wallpaper'>` +
          `<h3>Wallpaper</h3>` +
          `<button class='wm-button' data-wallpaper='gradient'>Gradient</button>` +
          `<button class='wm-button' data-wallpaper='ai_nature'>AI Nature</button>` +
          `<button class='wm-button' data-wallpaper='ai_cityscape'>AI Cityscape</button>` +
          `<button class='wm-button' data-wallpaper='ai_abstract'>AI Abstract</button>` +
          `<button class='wm-button' data-wallpaper='custom'>Custom Color</button>` +
          `<button class='wm-button' id='upload-wallpaper'>Upload</button>` +
          `<input type='file' id='upload-input' accept='image/*'>` +
        `</div>` +

        `<div class='category-menu' id='buttons'>` +
          `<h3>Buttons</h3>` +
          `<label>BG:<br><input id='btn-bg' class='wm-input' value='${BTN.bg}'></label>` +
          `<label>Hover BG:<br><input id='btn-hover' class='wm-input' value='${BTN.hover}'></label>` +
          `<label>Radius:<br><input id='btn-radius' class='wm-input' value='${BTN.radius}'></label>` +
          `<label>Font Size:<br><input id='btn-font' class='wm-input' value='${BTN.font}'></label>` +
          `<label>Padding:<br><input id='btn-pad' class='wm-input' value='${BTN.pad}'></label>` +
          `<button class='wm-button' id='apply-buttons'>Apply</button>` +
        `</div>` +

        `<div class='category-menu' id='animations'>` +
          `<h3>Animations</h3>` +
          `<label>Gradient Duration (s):<br><input type='number' id='anim-duration' class='wm-input' value='${ANIM.gradDur}' min='1'></label>` +
          `<button class='wm-button' id='apply-animations'>Apply</button>` +
        `</div>` +

        `<div class='category-menu' id='notes'>` +
          `<h3>Notes</h3>` +
          `<textarea id='notes-text' style='width:100%;height:200px;padding:8px;border:1px solid #ccc;border-radius:4px;'>${savedNotes}</textarea>` +
          `<button id='save-notes' class='wm-button'>Save Notes</button>` +
        `</div>` +

        `<div class='category-menu' id='todo'>` +
          `<h3>To-Do List</h3>` +
          `<input id='todo-input' placeholder='New task...'><button id='add-todo' class='wm-button'>Add</button>` +
          `<ul id='todo-list'></ul>` +
        `</div>` +

        `<div class='category-menu' id='timer'>` +
          `<h3>Timer</h3>` +
          `<span id='timer-display-general'>00:00:00</span>` +
          `<label><input type='checkbox' id='chk-show-screen' ${showTimerOnScreen?'checked':''}/> Show timer on screen</label><br>` +
          `<button id='timer-toggle-general' class='wm-button'>Start</button>` +
          `<button id='timer-reset-general'  class='wm-button'>Reset</button>` +
        `</div>` +

        `<div class='category-menu' id='extras'><h3>Extras</h3><p>More coming soon…</p></div>` +

      `</div>`;
    document.body.appendChild(menu);

    menu.querySelectorAll('.cat-btn').forEach(b=>{
      b.addEventListener('click',()=>{
        menu.querySelectorAll('.cat-btn').forEach(x=>x.classList.remove('active'));
        menu.querySelectorAll('.category-menu').forEach(x=>x.classList.remove('active'));
        b.classList.add('active');
        menu.querySelector('#'+b.dataset.cat).classList.add('active');
      });
    });

    const showM = ()=>{ overlay.style.display='block'; menu.classList.add('visible'); };
    const hideM = ()=>{ menu.classList.remove('visible'); overlay.style.display='none'; };

    btn.addEventListener('click',()=>{
      if(userPass){
        const p = prompt('Enter password:');
        if(p !== userPass) return;
      }
      showM();
    });
    document.addEventListener('keydown', e=>{
      if(e.key === toggleKey){
        if(menu.classList.contains('visible')) hideM();
        else {
          if(userPass){
            const p = prompt('Enter password:');
            if(p !== userPass) return;
          }
          showM();
        }
      }
    });
    menu.querySelector('#close-x').addEventListener('click', hideM);
    overlay.addEventListener('click', hideM);

    menu.querySelector('#apply-general').addEventListener('click', ()=>{
      autoUnpause = menu.querySelector('#chk-unpause').checked;
      pasteFast   = menu.querySelector('#chk-paste').checked;
      autoSpeed   = menu.querySelector('#chk-speed').checked;
      userPass    = menu.querySelector('#menu-pass').value;
      save(STORAGE.unpause, autoUnpause);
      save(STORAGE.pasteFast, pasteFast);
      save(STORAGE.autoSpeed, autoSpeed);
      save(STORAGE.password, userPass);
      save(STORAGE.keybind,  toggleKey);
      if(autoUnpause) enableUnpause();
      if(autoSpeed) applyAutoSpeed();
      hideM();
    });

    const disp = menu.querySelector('#timer-display-general'),
          btnT = menu.querySelector('#timer-toggle-general'),
          btnR = menu.querySelector('#timer-reset-general'),
          chkS = menu.querySelector('#chk-show-screen');
    function updateTimer(){
      const h = Math.floor(timerElapsed/3600).toString().padStart(2,'0'),
            m = Math.floor((timerElapsed%3600)/60).toString().padStart(2,'0'),
            s = (timerElapsed%60).toString().padStart(2,'0');
      disp.textContent = `${h}:${m}:${s}`;
      if(showTimerOnScreen && screenTimerEl) screenTimerEl.textContent = disp.textContent;
    }
    btnT.addEventListener('click', ()=>{
      if(timerInterval){
        clearInterval(timerInterval);
        timerInterval = null;
        btnT.textContent = 'Start';
      } else {
        createScreenTimer();
        if(showTimerOnScreen) screenTimerEl.style.display = 'block';
        timerInterval = setInterval(()=>{
          timerElapsed++;
          updateTimer();
        }, 1000);
        btnT.textContent = 'Stop';
      }
    });
    btnR.addEventListener('click', ()=>{
      clearInterval(timerInterval);
      timerInterval = null;
      timerElapsed = 0;
      updateTimer();
      btnT.textContent = 'Start';
    });
    chkS.addEventListener('change', e=>{
      showTimerOnScreen = e.target.checked;
      save(STORAGE.showTimer, showTimerOnScreen);
      if(screenTimerEl) screenTimerEl.style.display = showTimerOnScreen ? 'block' : 'none';
    });
  }

  /* -------------------
     9) INIT
     ------------------- */
  function wireUpWallpaperButtons(){
    const uploadInput = document.querySelector('#upload-input');
    document.body.addEventListener('click', e => {
      const btn = e.target;
      if (btn.matches('#wallpaper button[data-wallpaper]')) {
        const type = btn.getAttribute('data-wallpaper');
        if (type === 'custom') {
          const val = prompt('Enter a CSS background (color, gradient, etc):');
          if (val) changeWP(type, val);
        } else {
          changeWP(type, null);
        }
      }
      if (btn.id === 'upload-wallpaper') {
        uploadInput.click();
      }
    });
    uploadInput.addEventListener('change', e => {
      const file = e.target.files[0];
      if (!file) return;
      const reader = new FileReader();
      reader.onload = () => changeWP('upload', reader.result);
      reader.readAsDataURL(file);
    });
  }

  function init(){
    setupPaste();
    buildMenu();
    setupAIChatbot();           // ← initialize AI after menu exists
    createScreenTimer();
    wireUpWallpaperButtons();
    if(autoSpeed) applyAutoSpeed();
  }
  if(document.readyState==='loading')
    document.addEventListener('DOMContentLoaded', init);
  else
    init();

  // Restore wallpaper
  const wp = loadWP();
  if(wp) window.addEventListener('DOMContentLoaded', ()=>changeWP(wp.type, wp.val, false));

})();
长期地址
遇到问题?请前往 GitHub 提 Issues,或加Q群1031348184

赞助商

Fishcpy

广告

Rainyun

注册一下就行

Rainyun

一年攒够 12 元