Hide listings from blocked sellers or items. Shift-click item icons to block them instantly on lostcity.markets pages.
// ==UserScript==
// @name LostCity Markets: Additional Functions
// @namespace http://tampermonkey.net/
// @version 3.4
// @description Hide listings from blocked sellers or items. Shift-click item icons to block them instantly on lostcity.markets pages.
// @match https://lostcity.markets/*
// @grant none
// @license MIT
// ==/UserScript==
(function () {
'use strict';
const SELLER_KEY = 'blockedSellersList';
const ITEM_KEY = 'blockedItemsList';
function getList(key) {
const stored = localStorage.getItem(key);
return stored ? JSON.parse(stored) : [];
}
function saveList(key, list) {
localStorage.setItem(key, JSON.stringify(list));
}
function normalizeName(name) {
return name.trim().toLowerCase().replace(/\s+/g, ' ');
}
function hideListings() {
const blockedSellers = getList(SELLER_KEY).map(normalizeName);
const blockedItems = getList(ITEM_KEY).map(normalizeName);
const rows = document.querySelectorAll('tr');
rows.forEach(row => {
const sellerLink = row.querySelector('a[href^="/users/"]');
const itemImg = row.querySelector('img[alt$="Icon"]');
const sellerName = sellerLink?.textContent.trim();
const itemAlt = itemImg?.getAttribute('alt') || '';
const itemName = itemAlt.replace(/ icon$/i, '').trim();
const isBlockedSeller = sellerName && blockedSellers.includes(normalizeName(sellerName));
const isBlockedItem = itemName && blockedItems.includes(normalizeName(itemName));
row.style.display = (isBlockedSeller || isBlockedItem) ? 'none' : '';
});
}
function createButton(label, onClick, offsetY) {
const button = document.createElement('button');
button.textContent = label;
Object.assign(button.style, {
position: 'fixed',
top: `${offsetY}px`,
left: '20px',
zIndex: 10000,
width: '160px',
height: '40px',
padding: '8px',
backgroundColor: '#222',
color: '#fff',
border: 'none',
borderRadius: '6px',
cursor: 'pointer',
fontSize: '14px',
boxShadow: '0 2px 6px rgba(0,0,0,0.3)',
textAlign: 'center'
});
button.addEventListener('click', onClick);
document.body.appendChild(button);
}
function addBlockUnblockButtons() {
// Seller block
createButton('🔕 Block Seller', () => {
const name = prompt('Enter seller name to block:');
if (name) {
const list = getList(SELLER_KEY);
const norm = normalizeName(name);
if (!list.map(normalizeName).includes(norm)) {
list.push(name.trim());
saveList(SELLER_KEY, list);
hideListings();
alert(`Seller "${name}" has been blocked.`);
} else {
alert(`Seller "${name}" is already blocked.`);
}
}
}, 20);
// Seller unblock
createButton('✅ Unblock Seller', () => {
const list = getList(SELLER_KEY);
if (list.length === 0) return alert('Your seller block list is empty.');
const name = prompt(`Blocked sellers:\n${list.join(', ')}\n\nEnter seller name to unblock:`);
const norm = normalizeName(name);
const updated = list.filter(s => normalizeName(s) !== norm);
if (updated.length < list.length) {
saveList(SELLER_KEY, updated);
alert(`Seller "${name}" has been unblocked.`);
location.reload();
} else {
alert(`Seller "${name}" is not in your block list.`);
}
}, 70);
// Item block
createButton('📦 Block Item', () => {
const itemName = prompt('Enter item name to block (e.g., Runite Bar):');
if (itemName) {
const list = getList(ITEM_KEY);
const norm = normalizeName(itemName);
if (!list.map(normalizeName).includes(norm)) {
list.push(itemName.trim());
saveList(ITEM_KEY, list);
hideListings();
alert(`Item "${itemName}" has been blocked.`);
} else {
alert(`Item "${itemName}" is already blocked.`);
}
}
}, 120);
// Item unblock
createButton('📦 Unblock Item', () => {
const list = getList(ITEM_KEY);
if (list.length === 0) return alert('Your item block list is empty.');
const itemName = prompt(`Blocked items:\n${list.join(', ')}\n\nEnter item name to unblock:`);
const norm = normalizeName(itemName);
const updated = list.filter(i => normalizeName(i) !== norm);
if (updated.length < list.length) {
saveList(ITEM_KEY, updated);
alert(`Item "${itemName}" has been unblocked.`);
location.reload();
} else {
alert(`Item "${itemName}" is not in your block list.`);
}
}, 170);
}
function enableShiftClickBlocking() {
document.addEventListener('click', e => {
if (e.shiftKey && e.target.tagName === 'IMG' && e.target.alt.endsWith('Icon')) {
const itemName = e.target.alt.replace(/ icon$/i, '').trim();
const norm = normalizeName(itemName);
const list = getList(ITEM_KEY);
if (!list.map(normalizeName).includes(norm)) {
list.push(itemName);
saveList(ITEM_KEY, list);
hideListings();
alert(`Item "${itemName}" has been blocked via Shift+Click.`);
} else {
alert(`Item "${itemName}" is already blocked.`);
}
e.preventDefault();
e.stopPropagation();
}
}, true);
}
function addInstructionLabel() {
const label = document.createElement('div');
label.textContent = '💡 Shift-click an item icon to add it to your block list.';
Object.assign(label.style, {
position: 'fixed',
top: '220px',
left: '20px',
zIndex: 10000,
width: '260px',
padding: '10px',
backgroundColor: '#222',
color: '#fff',
border: 'none',
borderRadius: '6px',
fontSize: '13px',
fontFamily: 'sans-serif',
boxShadow: '0 2px 6px rgba(0,0,0,0.3)',
textAlign: 'center'
});
document.body.appendChild(label);
}
// Initialize
hideListings();
addBlockUnblockButtons();
enableShiftClickBlocking();
addInstructionLabel();
const observer = new MutationObserver(hideListings);
observer.observe(document.body, { childList: true, subtree: true });
})();