DeepCo Queue Notifier

Sends a notification when your queue hits a certain threshold

Versione datata 26/12/2025. Vedi la nuova versione l'ultima versione.

Dovrai installare un'estensione come Tampermonkey, Greasemonkey o Violentmonkey per installare questo script.

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

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Userscripts per installare questo script.

Dovrai installare un'estensione come ad esempio Tampermonkey per installare questo script.

Dovrai installare un gestore di script utente per installare questo script.

(Ho già un gestore di script utente, lasciamelo installare!)

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

(Ho già un gestore di stile utente, lasciamelo installare!)

// ==UserScript==
// @name         DeepCo Queue Notifier
// @namespace    https://deepco.app/
// @version      0.0.3
// @description  Sends a notification when your queue hits a certain threshold
// @author       NaN
// @match        https://deepco.app/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=deepco.app
// @license      MIT
// @grant        GM_notification
// @grant        GM_getValue
// @grant        GM_setValue
// ==/UserScript==

(function () {
  "use strict";

  const DEFAULT_THRESHOLD = 0;
  let currentObserver = null;
  let notificationSent = false;
  let lastElement = null;
  let notifyThreshold = GM_getValue("notifyThreshold", DEFAULT_THRESHOLD);

  function createSettingsButton() {
    const button = document.createElement("button");
    button.textContent = "⚙️ Queue Notifier";
    button.style.cssText = `
      position: fixed;
      top: 20px;
      right: 20px;
      z-index: 10000;
      padding: 10px 15px;
      background: #4a5568;
      color: white;
      border: none;
      border-radius: 8px;
      cursor: pointer;
      font-size: 14px;
      font-family: system-ui, -apple-system, sans-serif;
      box-shadow: 0 2px 8px rgba(0,0,0,0.3);
      transition: background 0.2s;
    `;

    button.onmouseover = () => (button.style.background = "#2d3748");
    button.onmouseout = () => (button.style.background = "#4a5568");
    button.onclick = showSettingsPrompt;

    document.body.appendChild(button);
  }

  function showSettingsPrompt() {
    const overlay = document.createElement("div");
    overlay.style.cssText = `
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background: rgba(0,0,0,0.5);
      z-index: 10001;
      display: flex;
      align-items: center;
      justify-content: center;
    `;

    const modal = document.createElement("div");
    modal.style.cssText = `
      background: white;
      padding: 30px;
      border-radius: 12px;
      box-shadow: 0 4px 16px rgba(0,0,0,0.3);
      max-width: 400px;
      font-family: system-ui, -apple-system, sans-serif;
    `;

    modal.innerHTML = `
      <h2 style="margin: 0 0 15px 0; color: #2d3748; font-size: 20px;">
        Queue Notifier Settings
      </h2>
      <p style="margin: 0 0 20px 0; color: #4a5568; font-size: 14px;">
        Get notified when your queue reaches this number or below:
      </p>
      <input
        type="number"
        id="threshold-input"
        value="${notifyThreshold}"
        min="0"
        style="
          color: black;
          width: 100%;
          padding: 10px;
          border: 2px solid #e2e8f0;
          border-radius: 6px;
          font-size: 16px;
          box-sizing: border-box;
        "
      />
      <div style="margin-top: 20px; display: flex; gap: 10px;">
        <button id="save-btn" style="
          flex: 1;
          padding: 10px;
          background: #4299e1;
          color: white;
          border: none;
          border-radius: 6px;
          cursor: pointer;
          font-size: 14px;
          font-weight: 500;
        ">Save</button>
        <button id="cancel-btn" style="
          flex: 1;
          padding: 10px;
          background: #e2e8f0;
          color: #2d3748;
          border: none;
          border-radius: 6px;
          cursor: pointer;
          font-size: 14px;
          font-weight: 500;
        ">Cancel</button>
      </div>
    `;

    overlay.appendChild(modal);
    document.body.appendChild(overlay);

    const input = modal.querySelector("#threshold-input");
    const saveBtn = modal.querySelector("#save-btn");
    const cancelBtn = modal.querySelector("#cancel-btn");

    input.focus();
    input.select();

    saveBtn.onclick = () => {
      const value = parseInt(input.value);
      if (!isNaN(value) && value >= 0) {
        notifyThreshold = value;
        GM_setValue("notifyThreshold", value);
        notificationSent = false; // Reset notification state
        console.log(`Threshold updated to: ${value}`);
        overlay.remove();
      } else {
        alert("Please enter a valid number (0 or greater)");
      }
    };

    cancelBtn.onclick = () => overlay.remove();
    overlay.onclick = (e) => {
      if (e.target === overlay) overlay.remove();
    };

    input.onkeypress = (e) => {
      if (e.key === "Enter") saveBtn.click();
    };
  }

  function checkQueueStatus() {
    const queueStatusElm = document.getElementById("queue-status");
    if (!queueStatusElm) return;

    if (lastElement && lastElement !== queueStatusElm) {
      console.log("Element was replaced, re-initializing observer");
      initObserver(queueStatusElm);
    }

    const innerText = queueStatusElm.innerText.trim();
    const queueCount = parseInt(innerText);

    console.log("Queue status text:", innerText);

    if (!isNaN(queueCount) && queueCount <= notifyThreshold) {
      if (!notificationSent) {
        console.log(
          `Sending notification - queue is at ${queueCount} (threshold: ${notifyThreshold})`
        );
        GM_notification({
          title: "DeepCo Queue Alert",
          text: `Your queue has ${queueCount} item${queueCount === 1 ? "" : "s"} left!`,
          timeout: 5000,
        });
        notificationSent = true;
      }
    } else if (queueCount > notifyThreshold) {
      notificationSent = false;
    }
  }

  function initObserver(element) {
    if (currentObserver) {
      currentObserver.disconnect();
    }

    lastElement = element;
    currentObserver = new MutationObserver(checkQueueStatus);
    currentObserver.observe(element, {
      childList: true,
      characterData: true,
      subtree: true,
    });
    console.log("Observer attached to element");
  }

  function init() {
    const queueStatusElm = document.getElementById("queue-status");
    if (queueStatusElm) {
      console.log("Found queue-status element");
      initObserver(queueStatusElm);
      checkQueueStatus();
    }
  }

  // Wait for initial element
  const checkInterval = setInterval(() => {
    if (document.getElementById("queue-status")) {
      clearInterval(checkInterval);
      init();
    }
  }, 500);

  // Create settings button once page loads
  if (document.readyState === "loading") {
    document.addEventListener("DOMContentLoaded", createSettingsButton);
  } else {
    createSettingsButton();
  }

  // Poll every 2 seconds to catch element replacements
  setInterval(checkQueueStatus, 2000);

  // Re-check when tab becomes visible
  document.addEventListener("visibilitychange", () => {
    if (!document.hidden) {
      checkQueueStatus();
    }
  });
})();