Greasy Fork

🐭️ MouseHunt - Item Links

Add links to the MouseHunt wiki, MHCT looter, MHDB, and Markethunt for items.

目前为 2023-03-05 提交的版本。查看 最新版本

// ==UserScript==
// @name         🐭️ MouseHunt - Item Links
// @version      1.4.3
// @description  Add links to the MouseHunt wiki, MHCT looter, MHDB, and Markethunt for items.
// @license      MIT
// @author       bradp
// @namespace    bradp
// @match        https://www.mousehuntgame.com/*
// @icon         https://brrad.com/mouse.png
// @grant        none
// @run-at       document-end
// @require      https://cdn.jsdelivr.net/npm/[email protected]/mousehunt-utils.js
// ==/UserScript==

((function () {
	'use strict';

	/**
	 * Return a node with links after grabbing the item ID and name from the page.
	 *
	 * @param {Object} args       Arguments to use for the links.
	 * @param {string} args.id    CSS selector for the item ID.
	 * @param {string} args.name  CSS selector for the item name.
	 * @param {string} args.class CSS class to add to the node.
	 *
	 * @return {false|string} False if no item ID or name found, otherwise HTML for links.
	 */
	const getLinksNode = (args) => {
		const itemInfo = document.querySelector(args.id);
		if (! itemInfo) {
			return false;
		}

		const itemID = itemInfo.getAttribute('data-item-id');
		const itemName = document.querySelector(args.name).textContent;
		if (! itemID || ! itemName) {
			return false;
		}

		const existingText = document.querySelector('.mh-item-info-text');
		if (existingText) {
			existingText.remove();
		}

		const newText = document.createElement('div');
		newText.classList.add('mh-item-info-text');

		if (args.class) {
			newText.classList.add(args.class);
		}

		// Add link to the wiki.
		newText.innerHTML = makeLink('Wiki', `https://mhwiki.hitgrab.com/wiki/index.php/${ itemName }`);

		// Link to MHCT, either converter or looter.
		const isConvertible = document.querySelector(args.id + ' .itemView-action.convertible');
		newText.innerHTML += (isConvertible && isConvertible.innerText)
			? makeLink('MHCT Converter', `https://www.mhct.win/converter.php?item=${ itemID }&timefilter=all_time`)
			: makeLink('MHCT Looter', `https://www.mhct.win/loot.php?item=${ itemID }&timefilter=all_time`);

		// Link to mhdb.
		const mhdbName = itemName.replace(/'/g, '');
		newText.innerHTML += makeLink('mhdb', `https://dbgames.info/mousehunt/items/${ mhdbName }`);

		// Link to markethunt.
		const isTradable = document.querySelectorAll('.itemView-sidebar-checklistItem.checked');
		if (args.forceType === 'marketplace' || (isTradable && isTradable.length === 2)) {
			newText.innerHTML += makeLink('Markethunt', `https://markethunt.vsong.ca/index.php?item_id=${ itemID }`);
		}

		return newText;
	};

	/**
	 * Append text to a node, either before or after another node.
	 *
	 * @param {Object} args         Arguments to use for the text.
	 * @param {string} args.parent  CSS selector for the parent node.
	 * @param {string} args.child   CSS selector for the child node.
	 * @param {string} args.content Text to append.
	 *
	 * @return {Node} The node that was appended to.
	 */
	const appendText = (args) => {
		const append = document.querySelector(args.parent);
		if (! append) {
			return false;
		}

		if (args.child) {
			const child = document.querySelector(args.child);
			if (child && args.content) {
				return append.insertBefore(args.content, child);
			}
		} else {
			return append.appendChild(args.content);
		}

		return false;
	};

	/**
	 * Add links to the marketplace page for an item.
	 */
	const addMarketplaceLinks = () => {
		appendText({
			parent: '.marketplaceView-item-titleActions',
			child: '.marketplaceView-userGold',

			content: getLinksNode({
				id: '.marketplaceView-item.view',
				name: '.marketplaceView-item-titleName',
				forceType: 'marketplace',
			})
		});
	};

	/**
	 * Add links to the item popup for an item.
	 */
	const addItemPopupLinks = () => {
		appendText({
			parent: '.itemView-header-name',
			content: getLinksNode({
				id: '.itemViewContainer',
				name: '.itemView-header-name span',
				class: 'mh-item-info-text-item-popup'
			}),
		});
	};

	/**
	 * Fix item qty bug - see https://greasyfork.org/en/scripts/445926-mousehunt-item-quantity-fix
	 */
	const fixItemQtyBug = () => {
		// Make sure we have the ID parameter.
		if (window.location.href.indexOf('i.php?id=') === -1) {
			return;
		}

		// Grab the item ID.
		const itemID = window.location.href.split('i.php?id=')[ 1 ];
		if (! itemID) {
			return;
		}

		// Make sure the quantity shown is 0.
		const qty = document.querySelector('.itemView-sidebar-quantity');
		if (! (qty && qty.textContent.indexOf('You Own:') !== -1)) {
			return;
		}

		// Grab the item slug.
		const itemName = document.querySelector('.itemViewContainer').getAttribute('data-item-type');
		if (! itemName) {
			return;
		}

		// redirect to item.php?item_type=itemName
		const newLocation = window.location.href.replaceAll(`i.php?id=${ itemID }`, `item.php?item_type=${ itemName }`);
		if (newLocation !== window.location.href) {
			window.location.href = newLocation;
		}
	};

	fixItemQtyBug();

	addStyles(`
	.mh-item-info-text {
		display: inline-block;
		margin-right: 10px;
	}

	.mh-item-info-text-item-popup {
		text-align: right;
		width: auto;
		position: relative;
		top: 12px;
		right: 12px;
		display: block;
		margin: 0;
	}

	.mh-item-links {
		margin-left: 5px;
	}

	.mh-item-links span {
		font-weight: normal;
		font-size: 11px;
	}

	.mh-item-links-map {
		padding-bottom: 5px;
	}

	.mh-item-links-map a {
		margin: 10px 10px 10px 0;
	}
	.mh-item-links-map .mousehuntActionButton.tiny {
		margin: 3px;
	}`);

	onAjaxRequest((request) => {
		if (! request.responseURL) {
			return;
		}

		if (request.responseURL.indexOf('managers/ajax/users/marketplace.php') !== -1) {
			addMarketplaceLinks();
		} else if (request.responseURL.indexOf('managers/ajax/users/userInventory.php') !== -1) {
			addItemPopupLinks();
		}
	}, null, true);

	// if we're on an item page, add the links.
	if (window.location.href.indexOf('item.php') !== -1) {
		addItemPopupLinks();
	}
})());