- // ==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));
- });
- })();