DeepCo Queue Notifier

Sends a notification when your queue hits a certain threshold

Устаревшая версия за 26.12.2025. Перейдите к последней версии.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Для установки этого скрипта вам необходимо установить расширение, такое как Tampermonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

// ==UserScript==
// @name         DeepCo Queue Notifier
// @namespace    https://deepco.app/
// @version      0.0.5
// @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);
  let settingsButton = null;

  function updateButtonText() {
    if (settingsButton) {
      settingsButton.textContent = `⚙️ Queue Notifier (${notifyThreshold})`;
    }
  }

  function createSettingsButton() {
    const button = document.createElement("button");
    button.textContent = `Queue Notifier (${notifyThreshold})`;
    button.className = `btn btn-sm btn-outline gap-2 font-mono join-item`
    button.style.cssText = `
      position: fixed;
      top: 20px;
      right: 20px;
      z-index: 10000;
      padding: 10px 15px;
      cursor: pointer;
      transition: background 0.2s;
    `;

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

    document.body.appendChild(button);
    settingsButton = 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.className = `text-sm p-2 card bg-base-100 text-base-content border border-base-300 rounded-box pt-4`
    modal.style.cssText = `
      padding: 30px;
      max-width: 400px;
    `;

    modal.innerHTML = `
      <h2 class="font-semibold tracking-widest uppercase text-xl" style="margin: 0 0 15px 0;">
        Queue Notifier Settings
      </h2>
      <p class="stat-title" style="margin: 0 0 20px 0; text-wrap: auto;">
        Get notified when your queue reaches this number or below:
      </p>
      <input
        type="number"
        id="threshold-input"
        value="${notifyThreshold}"
        class="stat-title"
        min="0"
        style="
          width: 100%;
          padding: 10px;
          border: 2px solid #e2e8f0;
          font-size: 16px;
          box-sizing: border-box;
        "
      />
      <div style="margin-top: 20px; display: flex; gap: 10px;">
        <button class="btn btn-sm btn-outline gap-2 font-mono join-item" id="save-btn" style="
          flex: 1;
          padding: 10px;
          cursor: pointer;
          font-size: 14px;
          font-weight: 500;
        ">Save</button>
        <button class="btn btn-sm btn-outline gap-2 font-mono join-item" id="cancel-btn" style="
          flex: 1;
          padding: 10px;
          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;
        updateButtonText();
        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();
    }
  });
})();