[GC] Organize SW Results

Blocked users can be synced but do not actually change anything in the SW results yet.

// ==UserScript==
// @name       [GC] Organize SW Results
// @namespace   https://gf.qytechs.cn/en/users/1225524-kaitlin
// @match				https://www.grundos.cafe/market/wizard*
// @match       https://www.grundos.cafe/guilds/guild/*/members*
// @match       https://www.grundos.cafe/block*
// @require  	  https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js
// @require     https://update.gf.qytechs.cn/scripts/487361/1389917/%5BGC%20%7C%20Library%5D%20-%20SSW%3A%20Savvy%20Shop%20Wiz.js
// @grant				GM.getValue
// @grant     	GM.setValue
// @grant				GM.listValues
// @license     MIT
// @version     2.0.1
// @author      Cupkait
// @icon        https://i.imgur.com/4Hm2e6z.png
// @description	 Blocked users can be synced but do not actually change anything in the SW results yet.

// ==/UserScript==

createSSWMenu();
addStyles();


let wizList = document.querySelector('.sw_results');
if (window.location.href.startsWith('https://www.grundos.cafe/market/wizard/') && wizList) {
    generateNewGrid();
}



async function grabData() {
    const resultsGrid = document.querySelector('.sw_results');
    const resultsRaw = resultsGrid.querySelectorAll('.data');
    const rawData = [];

    for (var i = 0; i < resultsRaw.length;) {
        var seller = resultsRaw[i].innerText;
      console.log(seller)
        var link = resultsRaw[i].innerHTML;
        var stock = parseInt(resultsRaw[i + 2].innerText,10);
        var price = parseInt(resultsRaw[i + 3].innerText.replace(/[^\d]/g, ''), 10);

        var row = {
            seller: seller,
            link: link,
            stock: stock,
            price: price
        };

        rawData.push(row);
        i = i + 4;
    }
    return rawData;
}

async function calculateValues() {
    let rawData = await grabData();

    let lowestPrice = Math.min(...rawData.map(item => item.price));
    rawData.forEach(item => {
        item.pricediff = item.price - lowestPrice;
    });

    return rawData;
}

async function getUsers() {
    let friendList = await GM.getValue('friendList', '[]');
    let guildsList = await GM.getValue('guildsList', '{}');
    let blockList = await GM.getValue('blockList', '[]');
    const guildMembers = Object.values(guildsList).flatMap(guild => guild.guildMembers);

    if (typeof friendList === 'string') {
        friendList = JSON.parse(friendList);
    }
    if (typeof guildMembers === 'string') {
        guildMembers = JSON.parse(guildMembers);
    }
    if (typeof blockList === 'string') {
        blockList = JSON.parse(blockList);
    }
    return { friendList, guildMembers, blockList };
}

async function createTableRow(item, friendList, guildMembers, blockList) {
    var price = item.price.toLocaleString() + " NP";
    let variance;
    let friendstatus = friendList.includes(item.seller);
    let guildstatus = guildMembers.includes(item.seller);
    let blockstatus = blockList.includes(item.seller);

    if (item.pricediff === 0) {
        variance = '<span style="color:green">— LOWEST —</span>';
    } else if (friendstatus || guildstatus) {
        variance = `<span style="color:red">(+${item.pricediff.toLocaleString()})</span>`;
    } else {
        variance = '—';
    }

    let row = document.createElement('tr');
    row.innerHTML = `
        <td>${item.link}</td>
        <td>${item.stock}</td>
        <td><strong>${price}</strong></td>
        <td><strong>${variance}</strong></td>
    `;

    if (friendstatus) {
        row.classList.add('friend');
    } else if (blockstatus) {
        row.classList.add('blocked');
    } else if (guildstatus) {
        row.classList.add('guild');
    }

    return row;
}

async function generateNewGrid() {
    const { friendList, guildMembers, blockList } = await getUsers();

    const newGrid = document.createElement('table');
    newGrid.innerHTML = `<thead><tr><th>Owner</th><th>Stock</th><th>Price</th><th>Variance</th></tr></thead>`;

    let rawData = await calculateValues();
    const newHeader = await updateHeader();

    rawData.sort((a, b) => {
        const aIsFriend = friendList.includes(a.seller);
        const bIsFriend = friendList.includes(b.seller);
        const aIsGuildMember = guildMembers.includes(a.seller);
        const bIsGuildMember = guildMembers.includes(b.seller);

        if ((aIsFriend || aIsGuildMember) && !(bIsFriend || bIsGuildMember)) return -1;
        if (!(aIsFriend || aIsGuildMember) && (bIsFriend || bIsGuildMember)) return 1;


        return 0;
    });

    const tbody = document.createElement('tbody');

    for (const item of rawData) {
        const row = await createTableRow(item, friendList, guildMembers, blockList);
        tbody.appendChild(row);
    }

    newGrid.appendChild(tbody);

    const oldGrid = document.querySelector('.sw_results');
    oldGrid.insertAdjacentElement('beforebegin', newGrid);
    oldGrid.style.display = 'none';
}

async function updateHeader() {



}











function addStyles() {
    const newGridStyle = document.createElement('style');
    newGridStyle.innerHTML = `
     #sswmenu {
        display: none;
        border-radius: 15px 15px 15px 0px;
        border-bottom: 3px solid;
        position: absolute;
        z-index: 999;
        width: 250px;
        height: 250px;
        bottom: 0%;
        left: 100%;
        margin: -3px;
        padding: 10px;
        background-color: #d2d0cc;
        box-shadow: 5px 0 5px rgba(0, 0, 0, 0.5);
    }
    #sswcontainer {
        position: relative;
        border-bottom: 3px solid;
        padding: 5px 10px 5px 0px;
        height: 30px;
        width: 100%;
        top: 00%;
        left: 0px;
        background-color: #d2d0cc;
        box-shadow: 5px 0 5px rgba(0, 0, 0, 0.5);
    }
    #sswsettings {
        position: relative;
        font-size: 16px;
        font-weight: bold;
        font-family: courier;
        border-radius: 5px;
        padding: 5px;
        width: 100%;
        height: auto;
        border: 1px solid rgb(204, 204, 204);
        cursor: pointer;
        background-color: lightgray;
    }
    #menubutton {
        height: 35px;
        width: 90%;
        margin: 5px;
    }
table {
    position: relative;
    min-width: 80%;
    margin: 1em auto;
    width: max-content;
    max-width: 100%;
    text-align: center;
    border-collapse: collapse;
}
th,
td {
    position: relative;
    padding: 4px;
    z-index: 3;
}
th {
    background-color: var(--grid_head);
}
tr {
    position: relative;
    min-width: 100%;
    margin: 1em auto;
    width: max-content;
    max-width: 100%;
    text-align: center;
    border-collapse: collapse;
}
tr:nth-child(even) {
    background-color: var(--grid_even);
}
tr:nth-child(odd) {
    background-color: var(--grid_odd);
}

.friend::after {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: #00801a54;
    z-index: 1;
}
.guild::after {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: #2c008054;
    z-index: 1;
}
    .blocked {
opacity:10%
}
	.blocked:hover {
	opacity:85%
}

    `;
    document.head.appendChild(newGridStyle);
}
















// SYNCING BELOW







function removeUsersManually() {
	var userInput = prompt(
		'Which username would you like to remove from your list? Enter one username then click OK.'
	);

	if (userInput !== null && userInput.trim() !== '') {
		var index = friendList.findIndex(name => name
			.toLowerCase() === userInput.trim().toLowerCase());
		if (index !== -1) {
			friendList.splice(index, 1);
			GM.setValue('friendList', friendList);
			console.log('Removed', userInput.trim(),
				'from the friend list.');
		} else {
			console.log(userInput.trim(),
				'not found in the friend list.');
		}

		if (window.location.href ===
			'https://www.grundos.cafe/market/wizard/') {

			if (confirm(
					'Do you want to reload the page to see the updated results?'
				)) {
				location.reload();
			}
		}

	} else {
		console.log('No username entered. Operation canceled.');
	}
}
$(ManualRemove).on('click', removeUsersManually);
async function syncFriendsList() {
	try {
		const response = await fetch(
			'https://www.grundos.cafe/neofriends/');
		const html = await response.text();
		const doc = new DOMParser().parseFromString(html,
			'text/html');
		const uniqueUsernames = new Set();

		doc.querySelectorAll(
				'div.market_grid [href*="/userlookup/?user="]')
			.forEach(function (element) {
				uniqueUsernames.add(element.getAttribute(
					'href').split('=')[1]);
			});

		console.log("Friends List Synced");
		return Array.from(uniqueUsernames);
	} catch (error) {
		console.error('Error fetching and extracting usernames:',
			error);
		return [];
	}

}
$(SyncFriends).on('click', async function () {
console.log("clicked")
	const usernames = await syncFriendsList();
	friendList = usernames;
	GM.setValue('friendList', friendList);
	console.log('Synced usernames:', usernames);
});
function syncBlockedList() {
	if (window.location.href === 'https://www.grundos.cafe/block/') {
		const blockList = $('.block_list').find('span').map(
			function () {
				return $(this).text();
			}).get();
		GM.setValue('blockList', blockList);
		console.log('blockList stored:', blockList);
	} else {
		if (confirm(
				'You can only do this from the Blocked Users page. Want to open it in a new tab?'
			)) {
			window.open('https://www.grundos.cafe/block/', '_blank');
		} else {
			console.log('User declined. No blocked sync occured.');
		}
	}
}
$(SyncBlocked).on('click', syncBlockedList);
function syncGuildMembers() {
    if (/^https:\/\/www\.grundos\.cafe\/guilds\/guild\/.+\/members\//.test(window.location.href)) {
        const userName = /user=(.*?)"/g.exec(document.body.innerHTML)[1];
        const guildIdentifier = window.location.href.match(/guild\/([^\/-]+)/)?.[1];
        const guildName = $('.guild-header strong').eq(0).text();
        const guildID = "guildID_" + guildIdentifier;
        const guildMembers = [...new Set($('div.member-grid [href*="/userlookup/?user="]')
            .map(function() {
                return $(this).attr('href').split('=')[1];
            })
            .filter(function(guildMember) {
                return guildMember !== userName;
            })
        )];

        GM.getValue('guildsList', {}).then(function(guildsList) {
            guildsList[guildID] = {
                'guildName': guildName,
                'guildMembers': guildMembers
            };

            GM.setValue('guildsList', guildsList);
        });
    } else {
        if (confirm('You can only do this from the Guild Members page. Want to open it in a new tab?')) {
            window.open('https://www.grundos.cafe/guilds/', '_blank');
        } else {
            console.log('User declined. No action occurred.');
        }
    }
}
$(SyncGuild).on('click', syncGuildMembers);



QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址