您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
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.4
- // @author Cupkait
- // @icon https://i.imgur.com/4Hm2e6z.png
- // @description 2/25/2024, 11:26:31 PM
- // ==/UserScript==
- // State variables
- let collect = false;
- let active = false;
- let customSearchUrl = null;
- // Constants
- const MAIN_SELECTOR = 'main .sdb-info';
- // Initialize style and UI
- const sdbStyle = addStyles();
- const collectContainer = createCollectContainer();
- document.querySelector(MAIN_SELECTOR).append(collectContainer);
- // Start script
- initialize();
- async function initialize() {
- collect = await GM.getValue('collect', false);
- active = await GM.getValue('active', false);
- customSearchUrl = await GM.getValue('customSearchUrl', null);
- if (collect) {
- showNextButtons();
- } else if (active) {
- enableNextPageNavigation();
- } else {
- showEnableButton();
- }
- }
- function addStyles() {
- 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;
- cursor: pointer;
- display: inline-block;
- }
- .completion-message {
- color: green;
- font-weight: bold;
- }
- .add-custom-search {
- display: inline-flex;
- align-items: center;
- justify-content: center;
- width: 30px;
- height: 30px;
- border-radius: 50%;
- background-color: var(--grid_head);
- border: 1px solid grey;
- cursor: pointer;
- font-size: 20px;
- vertical-align: middle;
- margin: 10px;
- }
- .custom-search-container {
- margin: 10px 0;
- display: flex;
- justify-content: center;
- align-items: center;
- flex-wrap: wrap;
- }
- .custom-search-input {
- padding: 5px;
- margin-right: 10px;
- width: 60%;
- border: 1px solid grey;
- }
- .custom-search-button {
- background-color: var(--grid_head);
- border: 1px solid grey;
- padding: 5px 15px;
- cursor: pointer;
- }
- `;
- document.head.appendChild(style);
- return style;
- }
- function createCollectContainer() {
- const container = document.createElement('div');
- container.classList.add('collect-sdb');
- return container;
- }
- function createButton(text, onClick) {
- const button = document.createElement('a');
- button.textContent = text;
- button.addEventListener('click', onClick);
- return button;
- }
- function removeAllButtons() {
- collectContainer.innerHTML = '';
- }
- function showEnableButton() {
- collectContainer.append(createButton('Begin SDB Data Collection', async () => {
- await GM.setValue('collect', true);
- showNextButtons();
- }));
- }
- function showNextButtons() {
- removeAllButtons();
- // Add standard collection buttons
- collectContainer.append(
- createButton('Collect full SDB', () => setActiveAndNavigate('https://www.grundos.cafe/safetydeposit/')),
- createButton('Collect quest only', () => setActiveAndNavigate('https://www.grundos.cafe/safetydeposit/?page=1&&max_rarity=89&view=100'))
- );
- // Add custom search button if a URL exists
- if (customSearchUrl) {
- const customButton = createButton('Custom Search', () => setActiveAndNavigate(customSearchUrl));
- const resetButton = createButton('Reset Custom', resetCustomSearch);
- collectContainer.append(customButton, resetButton);
- } else {
- // Add the plus button to add a custom search
- const addButton = document.createElement('span');
- addButton.innerHTML = '+'; // Plus sign
- addButton.title = 'Add custom search URL';
- addButton.classList.add('add-custom-search');
- addButton.addEventListener('click', showCustomSearchInput);
- collectContainer.append(addButton);
- }
- }
- function showCustomSearchInput() {
- // Remove the plus button
- const plusButton = document.querySelector('.add-custom-search');
- if (plusButton) plusButton.remove();
- // Create container for input and save button
- const customContainer = document.createElement('div');
- customContainer.classList.add('custom-search-container');
- // Create input for URL
- const urlInput = document.createElement('input');
- urlInput.type = 'text';
- urlInput.placeholder = 'Paste your custom scan URL here and save';
- urlInput.classList.add('custom-search-input');
- // Create save button
- const saveButton = document.createElement('button');
- saveButton.textContent = 'Save';
- saveButton.classList.add('custom-search-button');
- saveButton.addEventListener('click', () => saveCustomSearch(urlInput.value));
- // Create cancel button
- const cancelButton = document.createElement('button');
- cancelButton.textContent = 'Cancel';
- cancelButton.classList.add('custom-search-button');
- cancelButton.style.marginLeft = '5px';
- cancelButton.addEventListener('click', () => {
- customContainer.remove();
- showNextButtons(); // Re-show the buttons including the plus sign
- });
- // Append elements
- customContainer.append(urlInput, saveButton, cancelButton);
- collectContainer.append(customContainer);
- // Focus the input
- urlInput.focus();
- }
- async function saveCustomSearch(url) {
- if (!url || !url.trim()) {
- displayMessage('Please enter a valid URL');
- return;
- }
- // Validate URL format
- if (!url.startsWith('https://www.grundos.cafe/safetydeposit/')) {
- displayMessage('URL must start with https://www.grundos.cafe/safetydeposit/');
- return;
- }
- // Save the URL
- customSearchUrl = url.trim();
- await GM.setValue('customSearchUrl', customSearchUrl);
- // Remove the input container
- const customContainer = document.querySelector('.custom-search-container');
- if (customContainer) customContainer.remove();
- // Show success message
- displayMessage('Custom search URL saved!');
- // Redisplay buttons
- showNextButtons();
- }
- async function resetCustomSearch() {
- customSearchUrl = null;
- await GM.setValue('customSearchUrl', null);
- showNextButtons();
- displayMessage('Custom search has been reset.');
- }
- async function setActiveAndNavigate(url) {
- await Promise.all([
- GM.setValue('collect', false),
- GM.setValue('active', true)
- ]);
- window.location.href = url;
- }
- function enableNextPageNavigation() {
- removeAllButtons();
- collectContainer.append(createButton('Cancel/Restart Collection', cancelCollection));
- initTableProcessing();
- }
- function appendMessage(messageText) {
- const message = document.createElement('p');
- message.innerHTML = messageText;
- collectContainer.append(message);
- }
- async function initTableProcessing() {
- await processTableData();
- displayPageInfo();
- setupKeyboardNavigation();
- }
- async function loadSdbContents() {
- return await 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) {
- if (!data[i + 1] || !data[i + 2] || !data[i + 3] || !data[i + 4]) continue;
- const row = createRow(data, i);
- if (!row) continue;
- 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) {
- try {
- const nameElement = data[index + 1].querySelector('strong');
- const rarityElement = data[index + 1].querySelector('span');
- const imageElement = data[index + 2].querySelector('img');
- const quantityElement = data[index + 3];
- const typeElement = data[index + 4].querySelector('strong');
- if (!nameElement || !rarityElement || !imageElement || !quantityElement || !typeElement) {
- return null;
- }
- const rarityMatch = rarityElement.textContent.match(/\d+/);
- if (!rarityMatch) return null;
- return {
- n: nameElement.textContent,
- r: parseInt(rarityMatch[0]),
- p: imageElement.src.split('/').pop(),
- q: parseInt(quantityElement.textContent) || 0,
- t: typeElement.textContent,
- };
- } catch (error) {
- console.error('Error creating row:', error);
- return null;
- }
- }
- 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 pageOptions = document.querySelectorAll('#page option');
- const pageCount = pageOptions.length;
- const currentPage = parseInt(new URLSearchParams(window.location.search).get('page')) || 1;
- const sdbContents = await loadSdbContents();
- const totalItems = sdbContents.length;
- // Get end total (if available)
- let endTotal = 0;
- const totalText = document.querySelector('main div:nth-child(6)')?.childNodes[4]?.textContent;
- if (totalText) {
- endTotal = parseFloat(totalText.replace(/[^0-9.]/g, '').replace(/,/g, ''));
- }
- appendMessage(`Total items collected: <strong>${totalItems.toLocaleString()}</strong> <br>You are viewing page <strong>${currentPage.toLocaleString()}</strong> / <strong>${pageCount.toLocaleString()}</strong>.`);
- appendMessage(`Click "Next" or press the right arrow key to go to the next page.`);
- // Always show export buttons
- appendExportButtons();
- }
- function appendExportButtons() {
- // Check if buttons already exist
- if (!document.querySelector('.collect-sdb .export-csv-button') &&
- !document.querySelector('.collect-sdb .copy-clipboard-button')) {
- const csvButton = createButton('Export to CSV', exportToCSV);
- csvButton.classList.add('export-csv-button');
- const clipboardButton = createButton('Copy to Clipboard', copyToClipboard);
- clipboardButton.classList.add('copy-clipboard-button');
- collectContainer.append(csvButton, clipboardButton);
- appendMessage(`Export to CSV to make a spreadsheet of the results. Copy to Clipboard to paste into a Virtupets.net Checklist.`);
- }
- }
- async function exportToCSV() {
- try {
- const sdbContents = await loadSdbContents();
- if (sdbContents.length === 0) {
- displayMessage('No data to export. Please collect some data first.');
- return;
- }
- const csvContent = "data:text/csv;charset=utf-8," +
- "Name,Rarity,Image,Quantity,Type\n" +
- sdbContents.map(e => Object.values(e).join(",")).join("\n");
- const link = document.createElement("a");
- link.setAttribute("href", encodeURI(csvContent));
- link.setAttribute("download", `sdbContents_${new Date().toISOString().slice(0,10)}.csv`);
- document.body.appendChild(link);
- link.click();
- link.remove();
- displayMessage('Export complete!');
- } catch (err) {
- console.error('Error exporting to CSV:', err);
- displayMessage('Error exporting to CSV. Check console for details.');
- }
- }
- async function copyToClipboard() {
- try {
- const sdbContents = await loadSdbContents();
- if (sdbContents.length === 0) {
- displayMessage('No data to copy. Please collect some data first.');
- return;
- }
- await navigator.clipboard.writeText(JSON.stringify(sdbContents));
- displayMessage('Copy complete!');
- } catch (err) {
- console.error('Error copying to clipboard:', err);
- displayMessage('Error copying to clipboard. Check console for details.');
- }
- }
- function displayMessage(text) {
- let message = collectContainer.querySelector('.completion-message');
- if (!message) {
- message = document.createElement('p');
- message.classList.add('completion-message');
- collectContainer.append(message);
- }
- message.innerHTML = text;
- // Auto-clear message after 5 seconds
- setTimeout(() => {
- if (message.parentNode) {
- message.innerHTML = '';
- }
- }, 5000);
- }
- async function cancelCollection() {
- await Promise.all([
- GM.setValue('active', false),
- GM.setValue('sdbContents', [])
- ]);
- window.location.href = 'https://www.grundos.cafe/safetydeposit/';
- }