[GC] - SDB Contents Collection

2/25/2024, 11:26:31 PM

目前為 2025-04-28 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

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

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name        [GC] - SDB Contents Collection
// @namespace   https://greasyfork.org/en/users/1225524-kaitlin
// @match       https://www.grundos.cafe/safetydeposit/*
// @grant       GM.setValue
// @grant       GM.getValue
// @grant       GM.addStyle

// @license     MIT
// @version     1.3
// @author      Cupkait
// @icon        https://i.imgur.com/4Hm2e6z.png
// @description 2/25/2024, 11:26:31 PM
// ==/UserScript==


let collect = false;
let active = false;

const sdbStyle = createSdbStyle();
document.head.appendChild(sdbStyle);

const collectContainer = createCollectContainer();
document.querySelector('main .sdb-info').append(collectContainer);

initialize();

async function initialize() {
  collect = await GM.getValue('collect', false);
  active = await GM.getValue('active', false);
  collect ? showNextButtons() : active ? enableNextPageNavigation() : showEnableButton();
}

function createSdbStyle() {
  const style = document.createElement('style');
  style.innerHTML = `
    .collect-sdb {
      text-align: center;
      margin: 10px;
    }
    .collect-sdb a {
      background-color: var(--grid_head);
      border: 1px solid grey;
      padding: 5px 15px;
      margin: 10px;
    }
  `;
  return style;
}

function createCollectContainer() {
  const container = document.createElement('div');
  container.classList.add('collect-sdb');
  return container;
}

function showEnableButton() {
  collectContainer.append(createButton('Begin SDB Data Collection', () => {
    GM.setValue('collect', true).then(showNextButtons);
  }));
}

function showNextButtons() {
  removeAllButtons();
  collectContainer.append(
    createButton('Collect full SDB', () => setActiveAndNavigate('https://www.grundos.cafe/safetydeposit/?view=100')),
    createButton('Collect quest only', () => setActiveAndNavigate('https://www.grundos.cafe/safetydeposit/?page=1&&max_rarity=89&view=100'))
  );
}

function createButton(text, onClick) {
  const button = document.createElement('a');
  button.textContent = text;
  button.addEventListener('click', onClick);
  return button;
}

function removeAllButtons() {
  while (collectContainer.firstChild) collectContainer.firstChild.remove();
}

async function setActiveAndNavigate(url) {
  await Promise.all([GM.setValue('collect', false), GM.setValue('active', true)]);
  window.location.href = url;
}

function enableNextPageNavigation() {
  removeEnableButton();
  collectContainer.append(createButton('Cancel/Restart Collection', cancelCollection));
  initTableProcessing();
}

function removeEnableButton() {
  const enableButton = collectContainer.querySelector('button');
  if (enableButton) enableButton.remove();
}

function appendMessages(messageText) {
  const message = document.createElement('p');
  message.innerHTML = messageText;
  collectContainer.append(message);
}

async function initTableProcessing() {
  await processTableData();
  displayPageInfo();
  setupKeyboardNavigation();
}

async function loadSdbContents() {
  return GM.getValue('sdbContents', []);
}

async function saveSdbContents(contents) {
  await GM.setValue('sdbContents', contents);
}

async function processTableData() {
  const sdbContents = await loadSdbContents();
  const data = document.querySelectorAll('.data');
  const rows = [];

  for (let i = 0; i < data.length; i += 7) {
    const row = createRow(data, i);
    const existingItemIndex = sdbContents.findIndex(item => item.n === row.n);
    if (existingItemIndex > -1) sdbContents[existingItemIndex] = row;
    else sdbContents.push(row);
    rows.push(row);
  }

  await saveSdbContents(sdbContents);
}

function createRow(data, index) {
  return {
    n: data[index + 1].querySelector('strong').textContent,
    r: parseInt(data[index + 1].querySelector('span').textContent.match(/\d+/)[0]),
    p: data[index + 2].querySelector('img').src.split('/').pop(),
    q: parseInt(data[index + 3].textContent),
    t: data[index + 4].querySelector('strong').textContent,
  };
}

function setupKeyboardNavigation() {
  document.addEventListener('keydown', (event) => {
    if (event.key === 'ArrowRight' && !['INPUT', 'TEXTAREA'].includes(document.activeElement.tagName)) {
      const nextPageLink = [...document.querySelectorAll('.center a')].find(link => link.textContent.trim().startsWith('Next'));
      if (nextPageLink) nextPageLink.click();
    }
  });
}

async function displayPageInfo() {
  const pageCount = document.querySelectorAll('#page option').length;
  const currentPage = parseInt(new URLSearchParams(window.location.search).get('page')) || 1;
  const sdbContents = await loadSdbContents();
  const totalItems = sdbContents.length;
  const endTotal = parseFloat(document.querySelector('main div:nth-child(6)').childNodes[4].textContent.replace(/[^0-9.]/g, '').replace(/,/g, ''));

  console.log(endTotal)

  appendMessages(`Total items collected: <strong>${totalItems.toLocaleString()}</strong>  <br>You are viewing page <strong>${currentPage.toLocaleString()}</strong> / <strong>${pageCount.toLocaleString()}</strong>.`);
  appendMessages(`Click "Next" or press the right arrow key to go to the next page.`);

  if (totalItems === endTotal) appendExportButtons();
}

function appendExportButtons() {
  collectContainer.append(createButton('Export to CSV', exportToCSV), createButton('Copy to Clipboard', copyToClipboard));
  appendMessages(`Export to CSV to make a spreadsheet of the results. Copy to Clipboard to paste into a Virtupets.net Checklist.`)
}

function exportToCSV() {
  loadSdbContents().then(sdbContents => {
    const csvContent = "data:text/csv;charset=utf-8," + sdbContents.map(e => Object.values(e).join(",")).join("\n");
    const link = document.createElement("a");
    link.setAttribute("href", encodeURI(csvContent));
    link.setAttribute("download", "sdbContents.csv");
    document.body.appendChild(link);
    link.click();
    link.remove();
    displayCompletionMessage();
  });
}

async function copyToClipboard() {
  try {
    const sdbContents = await loadSdbContents();
    await navigator.clipboard.writeText(JSON.stringify(sdbContents));
    displayCompletionMessage();
  } catch (err) {
    console.error('Error copying to clipboard:', err);
  }
}


function displayCompletionMessage() {
  const collectContainer = document.querySelector('.collect-sdb'); // or whatever selector you need

  if (!collectContainer) {
    console.error('Collect container not found!');
    return;
  }

  let message = collectContainer.querySelector('.completion-message');

  if (!message) {
    message = document.createElement('p');
    message.classList.add('completion-message');
    collectContainer.append(message);
  }
  message.innerHTML = 'Copy complete! Press "Restart Collection" to return to your usual SDB view.';
}


async function cancelCollection() {
  await Promise.all([GM.setValue('active', false), GM.setValue('sdbContents', [])]);
  window.location.href = 'https://www.grundos.cafe/safetydeposit/?view=100';
}