Greasy Fork is available in English.

IsThereAnyDeal - Add G2A prices

add G2A prices on listings

// ==UserScript==
// @name         IsThereAnyDeal - Add G2A prices
// @namespace    http://tampermonkey.net/
// @version      0.4
// @description  add G2A prices on listings
// @author       Shuunen
// @match        *://*isthereanydeal.com/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    /* This part allow this script to access G2A cors protected webservice */
    jQuery.ajaxPrefilter(function(options) {
        if (options.crossDomain && jQuery.support.cors) {
            options.url = 'https://e2ea1efc.ngrok.io/' + options.url;
        }
    });

    // Date.now polyfill
    if (!Date.now) {
        Date.now = function now() {
            return new Date().getTime();
        };
    }

    var colorDefault = 'antiquewhite';
    var colorNice = 'gold';
    var colorGood = 'gold';
    var colorGreat = 'red';

    var g2aBaseUrl = 'https://www.g2a.com';
    var g2aSearchUrl = '/lucene/search/quick?phrase=';
    var g2aNormalSearchUrl = '/?search=';

    var proxyFailed = false;
    var pricesCache = null;
    try {
        pricesCache = JSON.parse(localStorage.g2aPriceCache);
    } catch (e) {
        pricesCache = {};
    }

    function timestamp(){
        return Math.round(Date.now() / 1000);
    }

    function searchPrice(gameId, title, platform, callback) {
        // platform is one of 'steam','origin','uplay'
        callback = callback || function(){ console.warn('callback not provided');};
        if(proxyFailed){
            callback({minPrice:1000});
            return;
        }
        var cacheKey = gameId + '-'+platform;
        if(pricesCache.hasOwnProperty(cacheKey)){
            console.log('found ' + title + ' ['+platform+'] price in cache');
            if(pricesCache[cacheKey].hasOwnProperty('savedOn')){
                var hoursAgo = (timestamp() - pricesCache[cacheKey].savedOn) / 3600;
                var maxHours = 1;
                if(hoursAgo < maxHours){
                    callback(pricesCache[cacheKey]);
                    return;
                } else {
                    console.log('cache entry '+cacheKey+' is more than '+maxHours+' hours old, will not use this cache entry...');
                }
            } else {
                console.log('cache entry '+cacheKey+' was not timestamped, will not use this cache entry...');
            }
        }
        var url = g2aBaseUrl + g2aSearchUrl + title + ' ' + platform + ' global';
        // replace spaces
        url = url.replace(/\s/g,'%20');
        var gameUrl = '';
        var minPrice = 1000;
        $.getJSON(url, function(data) {
            if(!data.docs || !data.docs.length){
                console.error('no results found for '+title+' on '+platform+' (GET', url ,')');
            } else {
                data.docs.forEach(function(game) {
                    if(game.slug.indexOf('dlc') === -1 && (game.minPrice <= minPrice)){
                        minPrice =  game.minPrice;
                        gameUrl = g2aBaseUrl + game.slug;
                    }
                });
            }
            // save price for platform in memory cache
            pricesCache[cacheKey] = {
                savedOn: timestamp(),
                minPrice: minPrice,
                gameUrl: gameUrl,
                platform: platform
            };
            // persist in localStorage
            localStorage.g2aPriceCache = JSON.stringify(pricesCache);
            setTimeout(function(){
                // callback after delay to space requests
                callback(pricesCache[cacheKey]);
            }, 300);
        }).fail(function(err){
            console.info('setting proxyFailed to true to avoid cascading failling requests');
            proxyFailed = true;
            callback({minPrice:1000});
            return;
        });
    }

    function searchPriceByLine(line, index) {
        var title = line.querySelector('.title a.noticeable').textContent;
        // Watch_Dogs€ 2 => watch dogs 2
        title = title.toLowerCase().replace(/[^a-z\s\d]/g,' ').replace(/\s+/g,' ').trim();
        var priceEl = line.querySelector('.currentBest');
        if(!priceEl){
            var minPriceDeal = 1000;
            line.querySelectorAll('.deals > a').forEach(function(priceDealEl){
                var priceDeal = parseFloat(priceDealEl.textContent.replace(',','.'));
                if(priceDeal < minPriceDeal){
                    priceEl = priceDealEl;
                    minPriceDeal = priceDeal;
                }
            });
        }
        if(!priceEl){
            console.error('cannot find price on line', line);
            return;
        }
        var price = parseFloat(priceEl.textContent.replace(',','.'));
        console.log(title, price);
        var platform = '';
        var gameId = line.getAttribute('data-plain');
        if(!gameId){
            console.error('cannot find game id on line', line);
            return;
        }
        var gameUrl = '';
        var minPrice = 1000;
        // mark line as loading
        line.style.filter = 'blur(5px) brightness(300%)';
        line.style.transition = 'filter .4s';
        setTimeout(function(){
            searchPrice(gameId, title, 'steam', function(results){
                if(results.minPrice < minPrice){
                    minPrice = results.minPrice;
                    gameUrl = results.gameUrl;
                    platform = results.platform;
                }
                searchPrice(gameId, title, 'origin', function(results){
                    if(results.minPrice < minPrice){
                        minPrice = results.minPrice;
                        gameUrl = results.gameUrl;
                        platform = results.platform;
                    }
                    searchPrice(gameId, title, 'uplay', function(results){
                        if(results.minPrice < minPrice){
                            minPrice = results.minPrice;
                            gameUrl = results.gameUrl;
                            platform = results.platform;
                        }
                        // update price in DOM
                        if (minPrice < price) {
                            console.info('found better price for ' + title + ' ['+platform+'] : ' + minPrice + '$' );
                            var reduc = (100 - Math.round((minPrice / price) * 100));
                            var color = (reduc > 80 ? colorGreat : (reduc > 50 ? colorGood : (reduc > 30 ? colorNice : colorDefault)));
                            var stl = ' style="color:'+color+'"';
                            var hrf = ' href="'+ gameUrl + '"';
                            var ttl = ' title="on ['+platform+'], ' + reduc + '% off !"';
                            var trg = ' target="_blank"';
                            priceEl.parentElement.innerHTML += '<a'+stl+hrf+ttl+trg+'>' + minPrice +'$ on G2A</a>';
                        } else {
                            console.log('didnt found better price for ' + title + ' than : ' + price + '$' );
                        }
                        var getPriceLink = line.querySelector('.g2a-get-price');
                        if(getPriceLink){
                            getPriceLink.style.display = 'none';
                        } else {
                            // console.log('cannot find the "Get price" link in order to hide it');
                        }
                        // let user check himself on G2A
                        var dealsEl = line.querySelector('.deals');
                        var cls = ' class="g2a-get-price manual"';
                        var href = ' href="'+g2aBaseUrl + g2aNormalSearchUrl + title +' global"';
                        var target = ' target="_blank"';
                        dealsEl.innerHTML = '<a'+cls+href+target+'>Check on G2A</a>' + dealsEl.innerHTML;
                        // remove loading styling
                        line.style.filter = '';
                    });
                });
            });
        }, index * 300);
    }

    function addGetPriceLink(line, index){
        var dealsEl = line.querySelector('.deals');
        dealsEl.innerHTML ='<div class="g2a-get-price">Get Price on G2A</div>' + dealsEl.innerHTML;
        var link = line.querySelector('.g2a-get-price');
        if(link){
            link.addEventListener('click',function(event){
                searchPriceByLine(line, index);
                link.style.display = 'none';
            });
        } else {
            console.error('impossible to find the "Get Price" button to listen the click to');
        }
    }

    function addGetAllPricesLink(){
        var container = document.querySelector('#orderByRight');
        container.innerHTML ='<div class="g2a-get-price all">Get ALL Prices on G2A</div>' + container.innerHTML;
        var link = container.querySelector('.g2a-get-price');
        if(link){
            link.addEventListener('click',function(event){
                document.querySelectorAll('#games .game').forEach(searchPriceByLine);
            });
        } else {
            console.error('impossible to find the "Get ALL Prices" button to listen the click to');
        }
    }

    function detectMouseoverGames(){
        var gameHovered = '';
        document.body.addEventListener('mouseover',function(event){
            var el = event.target;
            if(!el.classList.contains('game')){
                return;
            }
            var curGameHovered = el.getAttribute('data-plain');
            if(curGameHovered === gameHovered){
                return;
            }
            gameHovered = el.getAttribute('data-plain');
            // console.log('over', gameHovered);
            if(!el.querySelector('.g2a-get-price')){
                addGetPriceLink(el, 0);
            }
        });
    }

    function insertStyle() {
        var style = `<style class="getG2ApricesStyle">
.g2a-get-price {
background-color: darkslategrey;
padding: 1px 5px;
margin: 3px 0 -5px;
font-size: 10px;
float: left;
cursor: pointer;
}
.g2a-get-price.manual {
background-color: #333;
color: #999;
}
.g2a-get-price.all {
font-size: 12px;
margin: 0px 8px 4px;
padding: 2px 8px;
border: 1px dotted lightblue;
border-radius: 3px;
}
</style>`;
        $('body').append($(style));
    }

    // init
    detectMouseoverGames();
    insertStyle();
    addGetAllPricesLink();
})();