dbondan1gmail.com / PokevisionMod Updated

// ==UserScript==
// @name        PokevisionMod Updated
// @namespace   PokeModUpdated
// @description Pokevision Mod Updated
// @include     https://pokevision.com/*
// @version     1.3
// @grant       GM_addStyle
// ==/UserScript==

window.addEventListener('load', function() {
    if (Notification.permission !== "granted") {
        Notification.requestPermission();
    }
    //console.log("test");
    //setTimeout(function () {
    GM_addStyle('.leaflet-marker-icon-wrapper.leaflet-zoom-animated.leaflet-clickable { margin-left: -23.5px !important; margin-top: -22px !important; }');
    //POKEVISION AFK MOD - Take 2 22/07/2016
    console.log("%cLOADING POKEVISION MOD","color:lightblue");
    console.log("- Big thanks to ffejmania for the distance calculator");

    /*Sound effects, in case the narrator bugs up (happens a lot)
	Hopefully these guys don't mind we're using their sound :)
	http://ionden.com/a/plugins/ion.sound/static/sounds/button_tiny.mp3
*/
    var audio = new Audio('http://ionden.com/a/plugins/ion.sound/static/sounds/button_tiny.mp3');
    function blip() {
        audio.play();
    }

    var pokemonAlertList = { //Choose which pokemon you want to be alerted about!
        "Bulbasaur": true,
        "Ivysaur":true,
        "Venusaur":true,
        "Charmander":true,
        "Charmeleon":true,
        "Charizard":true,
        "Squirtle":true,
        "Wartortle":true,
        "Blastoise":true, 
        "Caterpie":false, 
        "Metapod":false,
        "Butterfree":true,
        "Weedle":false,
        "Kakuna":false,
        "Beedrill":true,
        "Pidgey":false, //Hell no
        "Pidgeotto":false,
        "Pidgeot":true,
        "Rattata":false,
        "Raticate":false,
        "Spearow":false,
        "Fearow":true,
        "Ekans":false,
        "Arbok":true,
        "Pikachu":true,
        "Raichu":true,
        "Sandshrew":true,
        "Sandslash":true,
        "Nidoran♀":false,
        "Nidorina":false,
        "Nidoqueen":true,
        "Nidoran♂":false,
        "Nidorino":false,
        "Nidoking":true,
        "Clefairy":false,
        "Clefable":true,
        "Vulpix":true,
        "Ninetales":true,
        "Jigglypuff":false,
        "Wigglytuff":true,
        "Zubat":false, //Hell no
        "Golbat":true,
        "Oddish":false,
        "Gloom":false,
        "Vileplume":true,
        "Paras":false,
        "Parasect":false,
        "Venonat":false,
        "Venomoth":true,
        "Diglett":true,
        "Dugtrio":true,
        "Meowth":false,
        "Persian":false,
        "Psyduck":false,
        "Golduck":true,
        "Mankey":false,
        "Primeape":true,
        "Growlithe":true,
        "Arcanine":true,
        "Poliwag":false,
        "Poliwhirl":true,
        "Poliwrath":true,
        "Abra":false,
        "Kadabra":true,
        "Alakazam":true,
        "Machop":true,
        "Machoke":true,
        "Machamp":true,
        "Bellsprout":false,
        "Weepinbell":false,
        "Victreebel":true,
        "Tentacool":false,
        "Tentacruel":true,
        "Geodude":false,
        "Graveler":true,
        "Golem":true,
        "Ponyta":true,
        "Rapidash":true,
        "Slowpoke":true,
        "Slowbro":true,
        "Magnemite":false,
        "Magneton":true,
        "Farfetch'd":true,
        "Doduo":false,
        "Dodrio":false,
        "Seel":false,
        "Dewgong":false,
        "Grimer":false,
        "Muk":true,
        "Shellder":false,
        "Cloyster":true,
        "Gastly":false,
        "Haunter":false,
        "Gengar":true,
        "Onix":true,
        "Drowzee":false,
        "Hypno":false,
        "Krabby":false,
        "Kingler":false,
        "Voltorb":false,
        "Electrode":true,
        "Exeggcute":false,
        "Exeggutor":true,
        "Cubone":false,
        "Marowak":true,
        "Hitmonlee":true,
        "Hitmonchan":true,
        "Lickitung":true,
        "Koffing":true,
        "Weezing":true,
        "Rhyhorn":false,
        "Rhydon":true,
        "Chansey":false,
        "Tangela":false,
        "Kangaskhan":true,
        "Horsea":false,
        "Seadra":false,
        "Goldeen":false,
        "Seaking":false,
        "Staryu":false,
        "Starmie":true,
        "Mr. Mime":true,
        "Scyther":true,
        "Jynx":false,
        "Electabuzz":true,
        "Magmar":true,
        "Pinsir":true,
        "Tauros":true,
        "Magikarp":false,
        "Gyarados":true,
        "Lapras":true,
        "Ditto":true,
        "Eevee":false,
        "Vaporeon":true,
        "Jolteon":true,
        "Flareon":true,
        "Porygon":true,
        "Omanyte":true,
        "Omastar":true,
        "Kabuto":true,
        "Kabutops":true,
        "Aerodactyl":true,
        "Snorlax":true,
        "Articuno":true,
        "Zapdos":true,
        "Moltres":true,
        "Dratini":true,
        "Dragonair":true,
        "Dragonite":true,
        "Mewtwo":true, 
        "Mew":true, //The dream
        set: function(n, value) {
            this[Object.keys(this)[n]] = value;
        }
    };
    var searchdistance = 500; //Are they worth the walk?
    getCookie();

    //Clean that side bar. Sorry website owners.
    $(".home-sidebar p:not(.home-sidebar-social), .home-sidebar ol, .home-sidebar h3").remove();
    $(".home-sidebar").append(`
<h1>That lazy afk mod</h1>
<p>Sit back, relax and it'll let you know when it's worth going outside :)<p>
<h3 id="distanceheader">` + (searchdistance == 1000 ? `No limit` : (`Alert distance <` + searchdistance + `m`)) + `</h3>
<input id="searchdistance" type="range" min="10" max="1000" value="` + searchdistance + `"></input>
<h3>Pokemon</h3>
<p><button id="deselectall">Deselect All</button><button id="selectall">Select All</button></p>
<ol id="alertlist" type="1">
</ol>
`);
    $(".home-map-scan").remove();

    var showUnwanted = true; //If it's not on the alert list should it be shown? This isn't a feature just yet...

    //Add pokemon to the list
    for (var key in pokemonAlertList) {
        if (key != "set") {
            var isChecked = pokemonAlertList[key]? "checked" : "";
            $("#alertlist").append('<li><input type="checkbox" '+isChecked+'></input> '+key+'</li>');
        }
    }

    //Bind events to the list items
    $("#selectall").click(function(){
        console.log("selectall");
        $("#alertlist li").each(function(e){
            $(this).find("input").prop("checked",true);
            var name = $(this).text().replace(/\s+/g, '');
            pokemonAlertList[name] = true;
        });
        setCookie();
    });
    $("#deselectall").click(function(){
        console.log("deselectall");
        $("#alertlist li").each(function(e){
            $(this).find("input").prop("checked",false);
            var name = $(this).text().replace(/\s+/g, '');
            pokemonAlertList[name] = false;
        });
        setCookie();
    });
    $("#searchdistance").mousemove(function(e){
        var dis = $(this).val();
        searchdistance = dis;
        if (dis < 1000) {
            $("#distanceheader").text("Alert distance <" + dis + "m");
        } else {
            $("#distanceheader").text("No limit");
        }
        setCookie();
    });
    $("#alertlist li input").click(function(e){
        var name = $(this).parent().text().replace(/\s+/g, '');
        var state = $(this).is(":checked");
        console.log(name,state);
        pokemonAlertList[name] = state; //Update the variable
        setCookie();
    });

    //The cool stuff
    App.home.updateMarkers = function() {
        e = App.home;
        if (!e.map) {
            return;
        }
        for (var i in e.pokemon) {
            var t = e.pokemon[i],
                o = t.expiration_time - Math.floor(+new Date() / 1000),
                n = e.markers['pokemon-' + i];
            if (o <= 0) {
                if (n) {
                    e.map.removeLayer(n);
                    delete e.markers['pokemon-' + i];
                }
                delete e.pokemon[i];
                continue;
            }
            if (!n) { //Check if it's on the alert list and if its wanted
                n = e.createMarker(i, t);
                foundPokemon(e.pokedex[t.pokemonId], getDistanceMetres(App.home.latitude, App.home.longitude, n._latlng.lat, n._latlng.lng));
            }
            n.updateLabel(e.secondsToString(o));
        }
    };

    function search() {
        console.log("Scanning...");
        App.home.findNearbyPokemon(App.home.latitude, App.home.longitude, !0);
        setTimeout(search,App.home.TIMER_SCAN_DELAY); //Scans at websites desired delay, please don't change this!
    }

    function foundPokemon(pokemon,d) {
        if (pokemonAlertList[pokemon] && (d <= searchdistance || searchdistance === "1000")) { //If it's within range
            console.log("FOUND POKEMON!" + pokemon + " " + d + " metres away");
            blip();
            notifyMe(pokemon, d);
            return;
        }
    }

    //Big thanks to ffejmania (and Lolologist) :)
    function getDistanceMetres(lat1,lon1,lat2,lon2) {
        var R = 6371; // Radius of the earth in km
        var dLat = deg2rad(lat2-lat1);  // deg2rad below
        var dLon = deg2rad(lon2-lon1);
        var a =
            Math.sin(dLat/2) * Math.sin(dLat/2) +
            Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) *
            Math.sin(dLon/2) * Math.sin(dLon/2)
        ;
        var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
        var d = Math.floor(R * c * 1000); // Distance in m
        return d;
    }
    function deg2rad(deg) {
        return deg * (Math.PI/180);
    }

    function setCookie() {
        var d = new Date();
        d.setTime(d.getTime() + (365*24*60*60*1000));
        var expires = "expires="+ d.toUTCString();
        var list = $('ol#alertlist li');
        var array = [];
        list.each(function (index) {
            if ($(this).find('input:checked').length > 0) {
                array.push(index);
            }
        });
        document.cookie = "shownPokemon=" + array.join(',') + "; " + expires;
        document.cookie = "searchDistance=" + searchdistance  + "; " + expires;
    }
    function getCookie() {
        var ca = document.cookie.split(';');
        for(var i = 0; i <ca.length; i++) {
            var c = ca[i];
            while (c.charAt(0)==' ') {
                c = c.substring(1);
            }
            if (c.indexOf("shownPokemon=") === 0) {
                var value = c.substring("shownPokemon=".length,c.length);
                var array = value.split(',');
                var list = $('ol#alertlist li');
                for (var a = 0; a < 151; a++) {
                    pokemonAlertList.set(a, false);
                }
                if (value.length > 0) {
                    for (var b = 0; b < array.length; b++) {
                        pokemonAlertList.set(array[b], true);
                    }
                }
            } else if (c.indexOf("searchDistance=") === 0) {
                var d = c.substring("searchDistance=".length,c.length);
                searchdistance = +d;
            }
        }
    }
    function getObjectKeyIndex(obj, keyToFind) {
        var i = 0, key;

        for (key in obj) {
            if (key == keyToFind) {
                return i;
            }

            i++;
        }

        return null;
    }
    function notifyMe(pokemon, d) {
        if (!Notification) {
            alert('Desktop notifications not available in your browser. Try Chromium.'); 
            return;
        }

        if (Notification.permission !== "granted")
            Notification.requestPermission();
        else {
            var id = getObjectKeyIndex(pokemonAlertList, pokemon);
            var notification = new Notification('Found a ' + pokemon, {
                icon: 'https://ugc.pokevision.com/images/pokemon/' + (id + 1) + '.png',
                body: "Found a " + pokemon+ " " + d + " metres away!",
            });
        }

    }

    //Start the repeating search function
    search();
    App.success(
        'The mod has started running! It will automatically refresh the search every 30 seconds' //Pop up
    );
    //}, 5000);
}, false);