[GC] - SDB Contents Collection

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

// ==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.0
// @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 p:nth-child(4)').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('.center').childNodes[4].textContent.replace(/[^0-9.]/g, '').replace(/,/g, ''));

  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();
  });
}

function copyToClipboard() {
  loadSdbContents().then(sdbContents => {
    navigator.clipboard.writeText(JSON.stringify(sdbContents)).then(displayCompletionMessage).catch(err => {
      console.error('Could not copy text: ', err);
    });
  });
}

function displayCompletionMessage() {
  let message = collectContainer.querySelector('.completion-message');
  let button = collectContainer.querySelector('button');
      button.textContent = 'Done Collecting'

  if (!message) {
    message = document.createElement('p');
    message.classList.add('completion-message');
    collectContainer.append(message);
  }
  message.innerHTML = 'Action complete! Press "Done Collecting" 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';
}