您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds buttons to search for similar giveaways and removes redirect from existing links.
// ==UserScript== // @name SteamGifts: Look for Similar // @namespace lainscripts_sg_look_for_similar // @version 4.3 // @description Adds buttons to search for similar giveaways and removes redirect from existing links. // @author lainverse // @match *://www.steamgifts.com/ // @match *://www.steamgifts.com/giveaway/* // @match *://www.steamgifts.com/giveaways/* // @match *://www.steamgifts.com/discussion/* // @grant none // ==/UserScript== // jshint esversion: 8 // jshint unused: true (function () { 'use strict'; // NodeList iterator polyfill (mostly for Safari) // https://jakearchibald.com/2014/iterators-gonna-iterate/ if (!NodeList.prototype[Symbol.iterator]) NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator]; (function (st) { st.id = 'sg_look_for_similar_stylesheet'; document.head.appendChild(st); st.sheet.insertRule( '.featured__heading .fa-search {' + ( 'font-size: 1.8em' ) + '}', 0); st.sheet.insertRule( '.lfsList {' + ( 'position: relative;' + 'display: inline-block;' + 'margin-right: -5px' ) + '}', 0); st.sheet.insertRule( '.lfsMenu { ' + ( 'display: none;' + 'position: absolute;' + 'min-width: max-content;' + 'background-color: #f9f9f9;' + 'box-shadow: 0px 4px 8px -2px #666;' + 'padding: 5px 0px' ) + '}', 0); st.sheet.insertRule( '.lfsOpts {' + ( 'display: block;' + 'font-weight: bold;' + 'min-width: max-content;' + 'white-space: nowrap;' + 'color: rgb(70, 86, 112) !important;' + 'padding: 5px 15px 5px 5px;' + 'text-decoration: none !important;' + 'font-size: 12px !important' ) + '}', 0); st.sheet.insertRule( '.lfsOpts:hover {' + ( 'background-color: #ddd' ) + '}', 0); st.sheet.insertRule( '.lfsList:hover > .lfsMenu {' + ( 'display: inline-block;' + 'z-index: 100' ) + '}', 0); st.sheet.insertRule( '.lfsList > .fa, .lfsList > a {' + ( 'display: block;' + 'padding: 2px 5px 0 5px;' + 'margin-left: 0' ) + '}', 0); st.sheet.insertRule( '.lfsList:hover .fa {' + ( 'color: rgb(70, 86, 112)' ) + '}', 0); st.sheet.insertRule( '.lfsList:hover {' + ( 'background-color: #f9f9f9;' + 'box-shadow: 0px 4px 8px 0px #666;' ) + '}', 0); })(document.createElement('style')); let loc = (location.pathname .replace(/^\/$/, '/giveaways') .replace(/^\/giveaway\/.*$/, '/giveaway') .replace(/\/search$/i, '') .replace(/^\/discussion\/.*/i, '/discussion')), type = loc.match(/\/([^/]+)\/?$/i)[1], locs = { local: { title: 'Here', id: 'lfsInLocal', loc: loc }, entered: { title: 'Entered', id: 'lfsInEntered', loc: '/giveaways/entered' }, giveaways: { title: 'All Giveaways', id: 'lfsInGiveaways', loc: '/giveaways' } }, contSearch = { giveaway: [locs.giveaways, locs.entered], won: [locs.local, locs.entered], giveaways: [locs.local, locs.entered], entered: [locs.local, locs.giveaways], discussion: [locs.giveaways, locs.entered], default: [locs.local] }, clHeader = ( '.giveaway__heading__name,' + '.featured__heading__medium,' + 'a.table__column__heading,' + '.markdown td > strong > a[href]' ), clHeaderIns = [ 'giveaway__heading__name', 'table__column__heading' ], caHeaderSib = [ 'giveaway__heading__thin', 'featured__heading__small' ]; if (!(type in contSearch)) type = 'default'; const ofClass = (itm, lst) => lst.some(cls => itm.classList.contains(cls)); const creator = document.createElement('outer'); creator.make = html => { creator.innerHTML = html; return creator.removeChild(creator.children[0]); }; function appendLFSLink(he) { let heLink = he.pathname ? he : he.querySelector('a'), heText = he.textContent; // Do not parse invite-only giveaways, non-giveaway and not-steam links if (heText == 'Invite Only' || (heLink && !/^\/giveaway\//i.test(heLink.pathname) && !/^store\.steampowered\.com|steamcommunity.com$/i.test(heLink.hostname))) return; // Do not add LFS button to a node with already existing LFS button if (he.parentNode.querySelector('.lfsList')) return; // Append LFS buttons let ovl = creator.make('<div class="lfsList"></div>'), //document.createElement('div'), mnu = creator.make('<div class="lfsMenu"></div>'); ovl.appendChild( he.parentNode.querySelector('a[href^="/giveaways/search?"]') || creator.make('<i class="giveaway__icon fa fa-search" />') ); ovl.appendChild(mnu); heText = '/search?q=' + encodeURIComponent( heText .replace(/(\s\(\d+(P|\sCopies)\))+$/i, '') .replace(/\.\.\.$/, '') ); for (let el of contSearch[type]) mnu.appendChild( creator.make(`<a class="lfsOpts" id="${el.id}" href="${el.loc + heText}">${el.title}</a>`) ); while (he.nextElementSibling && ofClass(he.nextElementSibling, caHeaderSib)) he = he.nextElementSibling; if (ofClass(he, clHeaderIns)) he.appendChild(ovl); else he.parentNode.insertBefore(ovl, he.nextElementSibling); } for (let header of document.querySelectorAll(clHeader)) appendLFSLink(header); (new MutationObserver(function (ms) { for (let m of ms) for (let node of m.addedNodes) if (node.nodeType === Node.ELEMENT_NODE) for (let header of node.querySelectorAll(clHeader)) appendLFSLink(header); })).observe(document.body, { childList: true, subtree: true }); document.addEventListener('click', e => { let lnk = e.target.closest('a'); if (!lnk) return; if (lnk.pathname === '/redirect' && lnk.search.startsWith('?url=')) lnk.href = decodeURIComponent(lnk.search.slice(5)); }); })();