GetCourse ID Collector

Виджет для сбора ID уроков на страницах GetCourse

当前为 2025-01-05 提交的版本,查看 最新版本

// ==UserScript==
// @name         GetCourse ID Collector
// @namespace    https://dev-postnov.ru/
// @version      1.6
// @description  Виджет для сбора ID уроков на страницах GetCourse
// @author       Daniil Postnov
// @match        *://*/teach/control/stream/*
// @match        *://*/teach/control/*
// @match        *://*/teach/*
// @match        *://*/teach
// @match        *://*/teach/control
// @grant        GM_setClipboard
// @grant        GM_notification
// @grant        GM_addStyle
// @license      MIT
// ==/UserScript==

(function () {
  'use strict';

  // Дожидаемся полной загрузки страницы
  window.addEventListener('load', () => {
    addWidget();
  });

  // Обработчик для динамической подгрузки контента
  const observer = new MutationObserver(() => {
    if (!document.querySelector('.get-id-widget-panel')) {
      addWidget();
    }
  });

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

  // Функция для добавления панели
  function addWidget() {
    if (document.querySelector('.get-id-widget-panel')) return;

    // Создаем панель
    const panel = document.createElement('div');
    panel.className = 'get-id-widget-panel';

    // Создаем кнопки
    const copyButton = document.createElement('button');
    const clearButton = document.createElement('button');
    const viewButton = document.createElement('button');

    copyButton.textContent = 'Скопировать ID уроков';
    clearButton.textContent = 'Очистить буфер';
    viewButton.textContent = 'Посмотреть буфер';

    // Добавляем кнопки в панель
    panel.appendChild(copyButton);
    panel.appendChild(clearButton);
    panel.appendChild(viewButton);
    document.body.appendChild(panel);

    // Добавляем тултип
    const tooltip = document.createElement('div');
    tooltip.className = 'get-id-widget-tooltip';
    document.body.appendChild(tooltip);

    // Добавляем стили
    applyStyles();

    // Функция для обновления текста кнопок
    const updateButtonText = (button, text, isError = false) => {
      button.textContent = text;
      button.style.backgroundColor = isError ? '#f44336' : '#fff';
    };

    // Функция для копирования ID уроков
    copyButton.addEventListener('click', () => {
      updateButtonText(copyButton, 'Собираем ID...');
      const links = document.querySelectorAll('.lesson-list li a, .training-row td a');
      const ids = Array.from(links)
        .map(link => {
          const match = link.href.match(/\/id\/(\d+)/);
          return match ? `'${match[1]}'` : null;
        })
        .filter(Boolean)
        .join(', ');

      if (ids) {
        GM_setClipboard(ids);
        GM_notification('ID уроков скопированы!', 'GetCourse Widget');
        updateButtonText(copyButton, 'Скопировано! ✅');
        setTimeout(() => updateButtonText(copyButton, 'Скопировать ID уроков'), 3000);
      } else {
        updateButtonText(copyButton, 'ID не найдены ❌', true);
        setTimeout(() => updateButtonText(copyButton, 'Скопировать ID уроков'), 3000);
      }
    });

    // Функция для очистки буфера обмена
    clearButton.addEventListener('click', () => {
      GM_setClipboard('');
      GM_notification('Буфер обмена очищен!', 'GetCourse Widget');
      updateButtonText(clearButton, 'Буфер очищен! ✅');
      setTimeout(() => updateButtonText(clearButton, 'Очистить буфер'), 3000);
    });

    // Функция для отображения буфера в тултипе
    viewButton.addEventListener('click', () => {
      navigator.clipboard.readText().then(bufferContent => {
        tooltip.innerHTML = bufferContent
          ? `<div class="tooltip-content">${bufferContent}</div>`
          : '<div class="tooltip-content">Буфер обмена пуст</div>';
        tooltip.classList.add('show');
        tooltip.style.display = 'block';
      }).catch(() => {
        tooltip.innerHTML = '<div class="tooltip-content">Ошибка чтения буфера</div>';
        tooltip.classList.add('show');
        tooltip.style.display = 'block';
      });
    });

    // Функция для закрытия тултипа
    tooltip.addEventListener('click', () => {
      tooltip.classList.remove('show');
      tooltip.style.display = 'none';
    });
  }

  // Функция для применения стилей
  function applyStyles() {
    GM_addStyle(`
      .get-id-widget-panel {
        position: fixed !important;
        top: 0 !important;
        right: 20px !important;
        z-index: 999999 !important;
        display: flex !important;
        align-items: center !important;
        padding: 10px !important;
        background-color: #8F93FF !important;
        border-radius: 0 0 12px 12px !important;
        box-shadow: 0 -4px 8px rgba(0, 0, 0, 0.2) !important;
        font-family: 'Roboto', sans-serif !important;
      }

      .get-id-widget-panel button {
        background-color: #fff !important;
        color: #222 !important;
        border: none !important;
        border-radius: 8px !important;
        padding: 10px 20px !important;
        margin: 0 5px !important;
        font-size: 14px !important;
        cursor: pointer !important;
        transition: background-color 0.2s ease !important;
      }

      .get-id-widget-panel button:hover {
        opacity: .85 !important;
      }

      .get-id-widget-tooltip {
        position: fixed !important;
        display: none !important;
        background-color: #fff !important;
        color: #222 !important;
        border: 1px solid #8F93FF !important;
        padding: 12px 16px !important;
        border-radius: 8px !important;
        font-size: 14px !important;
        box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2) !important;
        white-space: pre-line !important;
        max-width: 500px !important;
        z-index: 999999 !important;
      }

      .get-id-widget-tooltip.show {
        display: block !important;
      }

      .tooltip-content {
        max-height: 300px !important;
        overflow-y: auto !important;
      }
    `);
  }
})();