Sirotkin1 / Kittypet

// ==UserScript==
// @name         Kittypet
// @namespace    Sirotkin1
// @version      0.2
// @description  Дайте обратную связь пж а то я будто зря это все делаю
// @author       Сирота [1390991]
// @copyright    Wilhelm Birkner [https://vk.com/washclown]
// @updateURL https://openuserjs.org/meta/Sirotkin1/Kittypet.meta.js
// @downloadURL https://openuserjs.org/install/Sirotkin1/Kittypet.user.js
// @match        *://catwar.net/*
// @grant        none
// @license      MIT
// ==/UserScript==
(function () {
  'use strict';
  (function () {
    if (window.location.href !== 'https://catwar.net/cw3/') {
      return; // Выходим из скрипта, если URL не соответствует
    }
    const style = document.createElement('style');
    style.textContent = `
    #timer-window {
      position: fixed;
      top: 20px;
      left: 20px;
      background-color: #181818;
      color: #ffffff;
      padding: 10px;
      border: 1px solid #333;
      border-radius: 5px;
      z-index: 1000;
      font-family: Arial, sans-serif;
      cursor: grab;
      width: 380px;
    }
    #timer-window.dragging {
      cursor: grabbing;
    }
    #timer-header {
      margin-bottom: 5px;
      font-weight: bold;
      display: flex;
      justify-content: space-between;
      align-items: center;
      cursor: grab;
      color: #ddd;
    }
    #timer-header.dragging {
      cursor: grabbing;
    }
    #timer-container {
      display: grid;
      grid-template-columns: repeat(2, 1fr);
      gap: 5px;
    }
    .timer-group {
      margin-bottom: 5px;
      padding-bottom: 5px;
      border-bottom: 1px dotted #555;
    }
    .timer-group:last-child {
      border-bottom: none;
      margin-bottom: 0;
      padding-bottom: 0;
    }
    .timer-label {
      font-weight: bold;
      margin-bottom: 3px;
      display: block;
      color: #eee;
      font-size: 0.95em;
    }
    .timer-display {
      font-size: 1.1em;
      margin-bottom: 3px;
      color: #fff;
    }
    .timer-button {
      padding: 4px 8px;
      border: 1px solid #555;
      border-radius: 3px;
      cursor: pointer;
      background-color: #575757;
      color: #fff;
      margin-right: 3px;
      font-size: 0.9em;
    }
    .timer-button:hover {
      background-color: #575757;
    }
    .timer-button.start {
      background-color: #575757;
    }
    .timer-button.start:hover {
      background-color: #707070;
    }
    .timer-button.reset {
      background-color: #575757;
    }
    .timer-button.reset:hover {
      background-color: #707070;
    }
    .collapse-button {
      background: none;
      border: none;
      cursor: pointer;
      font-size: 1.2em;
      padding: 0;
      margin-left: 5px;
      color: #ddd;
    }
    .collapsed #timer-container {
      display: none;
    }
    .collapsed #timer-header {
      margin-bottom: 0;
    }

  `;
    document.head.appendChild(style);

    // HTML структура окна таймеров
    const timerWindow = document.createElement('div');
    timerWindow.id = 'timer-window';
    timerWindow.innerHTML = `
    <div id="timer-header">
      Таймеры
            <button id="collapse-timer-window" class="collapse-button">☰</button>
    </div>
    <div id="timer-container">
      <div class="timer-group">
        <span class="timer-label">Покормить курочку:</span>
        <div class="timer-display" id="timer-1-display">00:00:00</div>
        <button class="timer-button start" data-timer-id="1">Старт 6ч</button>
        <button class="timer-button reset" data-timer-id="1">Сброс</button>
      </div>
      <div class="timer-group">
        <span class="timer-label">Покормить Озика:</span>
        <div class="timer-display" id="timer-5-display">00:00:00</div>
        <button class="timer-button start" data-timer-id="5">Старт 6ч</button>
        <button class="timer-button reset" data-timer-id="5">Сброс</button>
      </div>
      <div class="timer-group">
        <span class="timer-label">Погладить Лучика:</span>
        <div class="timer-display" id="timer-3-display">00:00:00</div>
        <button class="timer-button start" data-timer-id="3">Старт 24ч</button>
        <button class="timer-button reset" data-timer-id="3">Сброс</button>
      </div>
      <div class="timer-group">
        <span class="timer-label">Потрогать миску:</span>
        <div class="timer-display" id="timer-6-display">00:00:00</div>
        <button class="timer-button start" data-timer-id="6">Старт 6ч</button>
        <button class="timer-button reset" data-timer-id="6">Сброс</button>
      </div>
      <div class="timer-group">
        <span class="timer-label">Поговорить с Алу:</span>
        <div class="timer-display" id="timer-2-display">00:00:00</div>
        <button class="timer-button start" data-timer-id="2">Старт 1ч</button>
        <button class="timer-button reset" data-timer-id="2">Сброс</button>
      </div>
       <div class="timer-group">
        <span class="timer-label">Джуди:</span>
        <div class="timer-display" id="timer-4-display">00:00:00</div>
        <button class="timer-button start" data-timer-id="4">Старт 3ч20м</button>
        <button class="timer-button reset" data-timer-id="4">Сброс</button>
      </div>
    </div>
  `;
    document.body.appendChild(timerWindow);

    const timerIntervals = {}; // Объект для хранения setInterval для каждого таймера
    const timerEndTimeKey = 'timerEndTimes';
    let isDragging = false;
    let dragOffsetX = 0;
    let dragOffsetY = 0;
    const timerHeader = document.getElementById('timer-header');
    const collapseButton = document.getElementById('collapse-timer-window');

    // Функция для форматирования времени в ЧЧ:MM:CC
    function formatTime(milliseconds) {
      let totalSeconds = Math.ceil(milliseconds / 1000);
      const hours = Math.floor(totalSeconds / 3600);
      totalSeconds %= 3600;
      const minutes = Math.floor(totalSeconds / 60);
      const seconds = totalSeconds % 60;
      return String(hours).padStart(2, '0') + ':' + String(minutes).padStart(2, '0') + ':' + String(seconds).padStart(2, '0');
    }

    // Функция для запуска таймера
    function startTimer(timerId, durationMs) {
      const displayElement = document.getElementById(`timer-${timerId}-display`);
      let endTime = Date.now() + durationMs;
      let savedEndTimes = JSON.parse(localStorage.getItem(timerEndTimeKey) || '{}');
      savedEndTimes[timerId] = endTime;
      localStorage.setItem(timerEndTimeKey, JSON.stringify(savedEndTimes));

      if (timerIntervals[timerId]) {
        clearInterval(timerIntervals[timerId]); // Очищаем предыдущий интервал, если есть
      }

      timerIntervals[timerId] = setInterval(() => {
        const timeLeft = endTime - Date.now();
        if (timeLeft <= 0) {
          clearInterval(timerIntervals[timerId]);
          displayElement.textContent = 'Время вышло!';
          alert(`Время для таймера ${timerId} истекло!`);
          savedEndTimes = JSON.parse(localStorage.getItem(timerEndTimeKey) || '{}');
          delete savedEndTimes[timerId]; // Удаляем из localStorage после истечения
          localStorage.setItem(timerEndTimeKey, JSON.stringify(savedEndTimes));
        }
        else {
          displayElement.textContent = formatTime(timeLeft);
        }
      }, 1000);
    }

    // Функция для сброса таймера
    function resetTimer(timerId) {
      clearInterval(timerIntervals[timerId]);
      document.getElementById(`timer-${timerId}-display`).textContent = '00:00:00';
      let savedEndTimes = JSON.parse(localStorage.getItem(timerEndTimeKey) || '{}');
      delete savedEndTimes[timerId];
      localStorage.setItem(timerEndTimeKey, JSON.stringify(savedEndTimes));
    }

    // Обработчики событий для кнопок
    timerWindow.addEventListener('click', function (event) {
      if (event.target.classList.contains('start')) {
        const timerId = event.target.dataset.timerId;
        let duration;
        switch (timerId) {
          case '1':
            duration = 6 * 60 * 60 * 1000;
            break; // 6 часов (Курочка)
          case '2':
            duration = 1 * 60 * 60 * 1000;
            break; // 1 час (Алу)
          case '3':
            duration = 24 * 60 * 60 * 1000;
            break; // 24 часа (Лучик)
          case '4':
            duration = (3 * 60 + 20) * 60 * 1000;
            break; // 3 часа 20 минут (Джуди)
          case '5':
            duration = 6 * 60 * 60 * 1000;
            break; // 6 часов (Озик)
          case '6':
            duration = 6 * 60 * 60 * 1000;
            break; // 6 часов (Миска)
          default:
            duration = 0;
        }
        if (duration > 0) {
          startTimer(timerId, duration);
        }
      }
      else if (event.target.classList.contains('reset')) {
        const timerId = event.target.dataset.timerId;
        resetTimer(timerId);
      }
    });

    // Функционал перетаскивания окна и сохранение позиции
    timerHeader.addEventListener('mousedown', function (e) {
      isDragging = true;
      dragOffsetX = e.clientX - timerWindow.offsetLeft;
      dragOffsetY = e.clientY - timerWindow.offsetTop;
      timerWindow.classList.add('dragging');
      timerHeader.classList.add('dragging');
    });

    document.addEventListener('mousemove', function (e) {
      if (!isDragging) return;
      timerWindow.style.left = e.clientX - dragOffsetX + 'px';
      timerWindow.style.top = e.clientY - dragOffsetY + 'px';
    });

    document.addEventListener('mouseup', function () {
      isDragging = false;
      timerWindow.classList.remove('dragging');
      timerHeader.classList.remove('dragging');
      // Сохранение позиции окна в localStorage
      localStorage.setItem('timerWindowLeft', timerWindow.style.left);
      localStorage.setItem('timerWindowTop', timerWindow.style.top);
    });

    // Функционал сворачивания окна и сохранение состояния
    collapseButton.addEventListener('click', function () {
      timerWindow.classList.toggle('collapsed');
      // Сохранение состояния свернутости в localStorage
      localStorage.setItem('timerWindowCollapsed', timerWindow.classList.contains('collapsed'));
    });

    // Восстановление таймеров, позиции и состояния при загрузке страницы
    function restoreTimers() {
      const savedEndTimes = JSON.parse(localStorage.getItem(timerEndTimeKey) || '{}');
      for (const timerId in savedEndTimes) {
        if (savedEndTimes.hasOwnProperty(timerId)) {
          const endTime = savedEndTimes[timerId];
          const timeLeft = endTime - Date.now();
          if (timeLeft > 0) {
            startTimer(timerId, timeLeft); // Перезапускаем таймер с оставшимся временем
          } // Если timeLeft <= 0, таймер уже должен был истечь или истечет сразу в setInterval
        }
      }

      // Восстановление позиции окна
      const savedLeft = localStorage.getItem('timerWindowLeft');
      const savedTop = localStorage.getItem('timerWindowTop');
      if (savedLeft) timerWindow.style.left = savedLeft;
      if (savedTop) timerWindow.style.top = savedTop;

      // Восстановление состояния свернутости окна
      const isCollapsed = localStorage.getItem('timerWindowCollapsed');
      if (isCollapsed === 'true') {
        timerWindow.classList.add('collapsed');
      }
      else {
        timerWindow.classList.remove('collapsed'); // Явно раскрываем, если в localStorage 'false' или null
      }
    }

    restoreTimers();

  })();

  let fillButtonClickCount = 0; // **Объявляем счетчик вне обработчика**
  const userIdPageUrl = 'https://catwar.net';

  function getUserIdFromPage() {
    return fetch(userIdPageUrl)
      .then(response => response.text())
      .then(html => {
        const parser = new DOMParser();
        const doc = parser.parseFromString(html, 'text/html');
        const userIdElement = doc.querySelector('#id_val');
        if (userIdElement) {
          return userIdElement.textContent;
        }
        else {
          console.error('Не удалось найти ID пользователя на странице.');
          return null;
        }
      })
      .catch(error => {
        console.error('Ошибка при получении страницы с ID:', error);
        return null;
      });
  }
  // Стили для элементов шаблона
  const style = document.createElement('style');
  style.innerHTML = `
    .template-field {
      margin-top: 10px;
      display: flex;
      align-items: center;
      flex-wrap: wrap;
      font-size: 13px;
      font-family: Arial, sans-serif;
    }
    .template-field input, .template-field select {
      margin: 0 5px;
      padding: 3px 5px;
      border: 1px solid #ccc;
      border-radius: 0px;
      font-size: 13px;
      max-width: 95px;
    }
    #templateSelect {
      margin-top: 5px;
      margin-bottom: 5px;
      font-size: 13px;
    }
    #dateOffset {
      width: 50px;
      font-size: 13px;
    }
    `;
  document.head.appendChild(style);

  // Шаблоны для разных блогов
  const templates = {
    // Руферы
    'blog696447': [{
        name: 'Передача предмета',
        template: 'Я, [[n]l[/n]ink{id}], передал(а) дому [{count}] предмет [{item_select}], [{points}], [url={screenshot}]Скриншот из истории[/url].'
      },
      {
        name: 'Очередь на перо',
        template: 'Я, [[n]l[/n]ink{id}], хочу встать в очередь на получение ({color_select}), {date}.'
      },
      {
        name: 'Выкуп перьев',
        template: 'Я, [[n]l[/n]ink{id}], хочу выкупить ({count}) ({color_select}), {date}.'
      }
    ],
  };

  // Формат даты
  const dateFormat = 'ДД.ММ.ГГГГ';
  const myTextarea = document.querySelector('textarea');
  if (myTextarea) {
    console.log('textarea найдена');
    const blogId = getBlogId();
    const availableTemplates = templates[blogId] || [];
    const templateContainer = document.createElement('div');
    templateContainer.id = 'template-container';
    myTextarea.parentNode.insertBefore(templateContainer, myTextarea.nextSibling);
    const templateSelect = document.createElement('select');
    templateSelect.id = 'templateSelect';
    availableTemplates.forEach((template, index) => {
      const option = document.createElement('option');
      option.value = index;
      option.text = template.name;
      templateSelect.appendChild(option);
    });
    templateContainer.appendChild(templateSelect);
    templateSelect.addEventListener('change', () => {
      const selectedIndex = templateSelect.value;
      const selectedTemplate = availableTemplates[selectedIndex].template;
      renderTemplate(selectedTemplate);
    });
    const dateOffsetLabel = document.createElement('label');
    dateOffsetLabel.textContent = 'Смещение даты:';
    dateOffsetLabel.htmlFor = 'dateOffset';
    templateContainer.appendChild(dateOffsetLabel);
    const dateOffsetInput = document.createElement('input');
    dateOffsetInput.type = 'number';
    dateOffsetInput.id = 'dateOffset';
    dateOffsetInput.value = 0;
    templateContainer.appendChild(dateOffsetInput);
    const fillButton = document.createElement('button');
    fillButton.textContent = 'Заполнить шаблон';
    fillButton.id = 'fillTemplateButton';
    fillButton.type = 'button';
    templateContainer.appendChild(fillButton);
    dateOffsetInput.addEventListener('input', () => {
      const template = availableTemplates[templateSelect.value].template;
      if (template.includes('{date}')) {
        renderTemplate(template);
      }
    });
    fillButton.addEventListener('click', () => {
      fillButtonClickCount++;
      console.log('Кнопка "Заполнить шаблон" нажата, счетчик:', fillButtonClickCount);
      const templateId = parseInt(document.getElementById('templateSelect').value);
      console.log('templateId:', templateId);
      const selectedTemplate = availableTemplates[templateId];
      console.log('selectedTemplate:', selectedTemplate);
      const data = {};
      const inputElements = templateContainer.querySelectorAll('.template-field input, .template-field select');
      inputElements.forEach(input => {
        data[input.id] = input.value;
      });
      console.log('data:', data);
      data['date'] = formatDate(getOffsetDate(parseInt(dateOffsetInput.value) || 0), dateFormat);
      let basePoints = 0;
      const pointSelectors = ['item_select', 'color_select']; // Список селекторов с баллами
      for (const selector of pointSelectors) {
        if (data[selector]) {
          basePoints = itemPoints[data[selector]] || 0;
          break; // Берем баллы первого найденного селектора
        }
      }
      data.points = basePoints;
      if (data.count) {
        data.points *= parseInt(data.count);
      }
      let filledTemplate = selectedTemplate.template;
      for (const key in data) {
        filledTemplate = filledTemplate.replace(new RegExp(`{${key}}`, 'g'), data[key]);
      }
      if (fillButtonClickCount === 1) {
        myTextarea.value = filledTemplate;
      }
      else {
        myTextarea.value += '\n' + filledTemplate;
      }
    });
    let itemPoints = {};
    fetch('https://raw.githubusercontent.com/Sirotkin1/points-data/refs/heads/main/points.json')
      .then(response => response.json())
      .then(data => {
        itemPoints = data;
        console.log('Баллы загружены:', itemPoints);
        if (availableTemplates.length > 0) {
          renderTemplate(availableTemplates[0].template);
        }
      })
      .catch(error => console.error('Ошибка загрузки JSON:', error));

    function renderTemplate(template) {
      const prevTemplateField = templateContainer.querySelector('.template-field');
      if (prevTemplateField) {
        prevTemplateField.remove();
      }
      const templateParts = template.split(/(\{[a-z_]+\})/);
      const templateField = document.createElement('div');
      templateField.classList.add('template-field');
      const inputCreators = {
        'id': () => {
          const input = document.createElement('input');
          input.type = 'text';
          return input;
        },
        'screenshot': () => {
          const input = document.createElement('input');
          input.type = 'text';
          return input;
        },
        'count': () => {
          const input = document.createElement('input');
          input.type = 'number';
          input.value = 1;
          input.min = 1;
          return input;
        },
        'color_select': () => {
          const select = document.createElement('select');
          const selectedTemplateName = availableTemplates[templateSelect.value].name;
          let colors = Object.keys(itemPoints);
          if (selectedTemplateName === 'Очередь на перо' || selectedTemplateName === 'Выкуп перьев') {
            colors = colors.filter(key => key.includes('перо'));
          }
          colors.forEach(color => {
            const option = document.createElement('option');
            option.value = color;
            option.text = color;
            select.appendChild(option);
          });
          return select;
        },
        'item_select': () => {
          const select = document.createElement('select');
          const selectedTemplateName = availableTemplates[templateSelect.value].name;
          let items = Object.keys(itemPoints);
          if (selectedTemplateName === 'Очередь на перо' || selectedTemplateName === 'Выкуп перьев') {
            return select; // Возвращаем пустой select
          }
          items.forEach(item => {
            const option = document.createElement('option');
            option.value = item;
            option.text = item;
            select.appendChild(option);
          });
          return select;
        },
        'shell_type': () => {
          const select = document.createElement('select');
          const types = ['обычная', 'блестящая', 'редкая'];
          types.forEach(type => {
            const option = document.createElement('option');
            option.value = type;
            option.text = type;
            select.appendChild(option);
          });
          return select;
        },
        'location': () => {
          const input = document.createElement('input');
          input.type = 'text';
          input.placeholder = 'Местоположение';
          return input;
        },
        'time': () => {
          const input = document.createElement('input');
          input.type = 'time';
          return input;
        },
        'checkbox_option': () => {
          const checkbox = document.createElement('input');
          checkbox.type = 'checkbox';
          return checkbox;
        },
        'range_value': () => {
          const input = document.createElement('input');
          input.type = 'range';
          input.min = 0;
          input.max = 100;
          return input;
        }
      };
      templateParts.forEach((part) => {
        if (part.startsWith('{')) {
          const variableName = part.slice(1, -1);
          const creator = inputCreators[variableName];
          if (creator) {
            const inputElement = creator();
            inputElement.id = variableName;
            templateField.appendChild(inputElement);
          }
        }
        else {
          const textSpan = document.createElement('span');
          textSpan.innerHTML = part.replace(/\[\[n\]\\`l\\`\[\/n\]/g, '[n]`l`[/n]');
          templateField.appendChild(textSpan);
        }
      });
      templateContainer.appendChild(templateField);
      getUserIdFromPage().then(userId => {
        if (userId) {
          const idInput = templateContainer.querySelector('#id');
          if (idInput) {
            idInput.value = userId;
          }
        }
      });
      updateDateLabel();
    }

    function formatDate(date, format) {
      const year = date.getFullYear();
      const month = (date.getMonth() + 1).toString().padStart(2, '0');
      const day = date.getDate().toString().padStart(2, '0');
      return format.replace('ГГГГ', year).replace('ММ', month).replace('ДД', day);
    }

    function getOffsetDate(offset) {
      const today = new Date();
      const offsetDate = new Date(today);
      offsetDate.setDate(today.getDate() + offset);
      return offsetDate;
    }

    function updateDateLabel() {
      const offset = parseInt(dateOffsetInput.value) || 0;
      const offsetDate = getOffsetDate(offset);
      console.log('Текущая дата:', formatDate(offsetDate, dateFormat));
    }

    function getBlogId() {
      const match = window.location.pathname.match(/\/blog(\d+)/);
      if (match) {
        return 'blog' + match[1];
      }
      return null;
    }
  }
})();