Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pokemon Notifications #343

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions src/routes/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const router = express.Router();
const map = require('../data/map.js');
const utils = require('../services/utils.js');
const masterfile = require('../../static/data/masterfile.json');
const { config } = require('../services/discord.js');
const skipForms = ['shadow', 'purified'];

router.get('/get_data', async (req, res) => {
Expand Down Expand Up @@ -57,6 +58,31 @@ const getSettings = (perms) => {
const level50String = i18n.__('filter_level50_stats');
const level51String = i18n.__('filter_level51_stats');
const weatherDetailsString = i18n.__('settings_weather_details');
const pokemonNotificationsString = i18n.__('settings_pokemon_notifications');

// Check if perms is not set and discord config not set, then allow all permissions
if (!config.discord.enabled && !perms) {
perms = {
map: true,
pokemon: true,
raids: true,
gyms: true,
pokestops: true,
quests: true,
lures: true,
invasions: true,
spawnpoints: true,
iv: true,
pvp: true,
s2cells: true,
submissionCells: true,
nests: true,
portals: true,
scanAreas: true,
weather: true,
devices: true,
};
}

if (perms.pokemon) {
/*
Expand Down Expand Up @@ -98,6 +124,14 @@ const getSettings = (perms) => {
'filter': generateShowHideButtons('pokemon-timers', 'pokemon-timers'),
'type': pokemonSettingsString,
});
settingsData.push({
'id': {
'sort': utils.zeroPad(3, 3),
},
'name': pokemonNotificationsString,
'filter': generateShowHideButtons('pokemon-notifications', 'pokemon-notifications'),
'type': pokemonSettingsString,
});
}
if (perms.gyms || perms.raids) {
settingsData.push({
Expand Down
2 changes: 2 additions & 0 deletions src/views/header.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<link rel="stylesheet" type="text/css" href="https://unpkg.com/[email protected]/dist/MarkerCluster.css" />
<link rel="stylesheet" type="text/css" href="https://unpkg.com/[email protected]/dist/MarkerCluster.Default.css" />
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/L.Control.Locate.min.css" />
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css" />
<link rel="stylesheet" type="text/css" href="/css/all.css" />

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
Expand All @@ -27,6 +28,7 @@
<script type="text/javascript" src="https://cdn.datatables.net/v/bs4/dt-1.10.18/r-2.2.2/rg-1.1.0/sc-1.5.0/datatables.min.js"></script>
<script type="text/javascript" src="https://unpkg.com/[email protected]/dist/leaflet.markercluster.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/[email protected]/dist/L.Control.Locate.min.js" charset="utf-8"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js"></script>
{{#google_analytics_id}}
<script type="text/javascript" src="//google-analytics.com/analytics.js"></script>
{{/google_analytics_id}}
Expand Down
86 changes: 81 additions & 5 deletions static/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ let showPopupPvp;
let showMinPokePopup;
let showWeatherDetails;

let showPokemonNotifications;

let tileLayer;
let nestLayer = new L.LayerGroup();
let scanAreaLayer = new L.LayerGroup();
Expand All @@ -135,6 +137,8 @@ let scanAreasDb = {};
let cpMultipliers = {};
let defaultRarity = {};

let pokemonNotificationsSent = {};

let skipForms = ['Shadow', 'Purified'];

const kanto = [1, 151];
Expand Down Expand Up @@ -430,6 +434,7 @@ $(function () {
portal: portalFilterNew,
weather: weatherFilterNew,
device: deviceFilterNew,
// TODO: Export all settings
};
let json = JSON.stringify(settings);
let el = document.createElement('a');
Expand Down Expand Up @@ -1170,6 +1175,9 @@ function loadStorage () {
if (defaultSettings['level51-stats'] === undefined) {
defaultSettings['level51-stats'] = { show: configPvp.l51stats };
}
if (defaultSettings['pokemon-notifications'] == undefined) {
defaultSettings['pokemon-notifications'] = { show: false }; // TODO: Configurable as default value
}
store('settings', JSON.stringify(defaultSettings));
settings = defaultSettings;
} else {
Expand Down Expand Up @@ -1234,6 +1242,9 @@ function loadStorage () {
if (settings['level51-stats'] === undefined) {
settings['level51-stats'] = { show: configPvp.l51stats };
}
if (settings['pokemon-notifications'] === undefined) {
settings['pokemon-notifications'] = { show: false }; // TODO: Configurable as default value
}
}
clusterPokemon = settings['pokemon-cluster'].show;
clusterGyms = settings['gym-cluster'].show;
Expand All @@ -1255,6 +1266,7 @@ function loadStorage () {
showLevel41Stats = settings['level41-stats'].show;
showLevel50Stats = settings['level50-stats'].show;
showLevel51Stats = settings['level51-stats'].show;
showPokemonNotifications = settings['pokemon-notifications'].show;
}

function initMap () {
Expand Down Expand Up @@ -1577,6 +1589,7 @@ function initMap () {
const newShowLevel41Stats = settingsNew['level41-stats'].show;
const newShowLevel50Stats = settingsNew['level50-stats'].show;
const newShowLevel51Stats = settingsNew['level51-stats'].show;
const newShowPokemonNotifications = settingsNew['pokemon-notifications'].show;
if (clusterPokemon !== newClusterPokemon ||
showPokemonGlow !== newShowPokemonGlow ||
showPokemonTimers !== newShowPokemonTimers ||
Expand All @@ -1586,7 +1599,8 @@ function initMap () {
showLevel40Stats !== newShowLevel40Stats ||
showLevel41Stats !== newShowLevel41Stats ||
showLevel50Stats !== newShowLevel50Stats ||
showLevel51Stats !== newShowLevel51Stats) {
showLevel51Stats !== newShowLevel51Stats ||
showPokemonNotifications !== newShowPokemonNotifications) {
$.each(pokemonMarkers, function (index, pokemon) {
if (clusterPokemon) {
clusters.removeLayer(pokemon.marker);
Expand Down Expand Up @@ -1647,6 +1661,7 @@ function initMap () {
showLevel41Stats = newShowLevel41Stats;
showLevel50Stats = newShowLevel50Stats;
showLevel51Stats = newShowLevel51Stats;
showPokemonNotifications = newShowPokemonNotifications;
store('show_pokemon_timers', newShowPokemonTimers);
store('show_raid_timers', newShowRaidTimers);
store('show_invasion_timers', newShowInvasionTimers);
Expand All @@ -1662,6 +1677,7 @@ function initMap () {
store('level41_stats', newShowLevel41Stats);
store('level50_stats', newShowLevel50Stats);
store('level51_stats', newShowLevel51Stats);
store('show_pokemon_notifications', newShowPokemonNotifications);

if (pokemonMarkers.length === 0 ||
gymMarkers.length === 0 ||
Expand Down Expand Up @@ -1938,7 +1954,7 @@ function loadSearchData (id, value) {
}

function centerOnMap(lat, lon) {
$('#searchModal').modal('toggle');
$('#searchModal').modal('hide');
let latlng = new L.LatLng(lat, lon);
let zoom = maxZoom;
map.setView(latlng, zoom);
Expand Down Expand Up @@ -2411,6 +2427,9 @@ function loadData () {
} else {
pokemon.marker.addTo(map);
}
// Show Pokemon notification
// TODO: Check if setting is set for notifications
showPokemonNotification(pokemon);

} else {
if (oldPokemon.expire_timestamp !== pokemon.expire_timestamp) {
Expand Down Expand Up @@ -3081,7 +3100,7 @@ const getPokemonPopupContent = (pokemon) => {
const getIV = (pokemon) => {
if (pokemon.atk_iv !== null && pokemon.atk_iv !== undefined && popupDetails.pokemon.iv) {
const ivColors = { 0: 'red', 66: 'orange', 82: 'yellow', 100: 'green' }
const ivPercent = ((pokemon.atk_iv + pokemon.def_iv + pokemon.sta_iv) / .45).toFixed(2);
const ivPercent = calculateIV(pokemon);
let selectedColor
Object.keys(ivColors).forEach(range => ivPercent >= parseInt(range) ? selectedColor = ivColors[range] : '');
return `
Expand Down Expand Up @@ -4732,7 +4751,8 @@ function manageSelectButton(e, isNew) {
type === 'pvp-level40-stats' ||
type === 'pvp-level41-stats' ||
type === 'pvp-level50-stats' ||
type === 'pvp-level51-stats') {
type === 'pvp-level51-stats' ||
type === 'pokemon-notifications') {
switch (info) {
case 'hide':
shouldShow = settingsNew[id].show === false;
Expand Down Expand Up @@ -5264,7 +5284,8 @@ function manageSelectButton(e, isNew) {
type === 'pvp-level40-stats' ||
type === 'pvp-level41-stats' ||
type === 'pvp-level50-stats' ||
type === 'pvp-level51-stats') {
type === 'pvp-level51-stats' ||
type === 'pokemon-notifications') {
switch (info) {
case 'hide':
settingsNew[id].show = false;
Expand Down Expand Up @@ -6135,6 +6156,58 @@ function getCpAtLevel(id, form, level, isMax) {
return 0;
}

const showPokemonNotification = (pokemon) => {
// Check if we have at least rendered the map once before showing notifications
if (lastUpdate === 0)
return;

// Check if pokemon notifications are enabled
if (!showPokemonNotifications) {
return;
}
if (pokemonNotificationsSent[pokemon.id]) {
// Prevent notifications of the same pokemon twice
return;
}
pokemonNotificationsSent[pokemon.id] = true;
const iv = pokemon.atk_iv !== null ? calculateIV(pokemon) : '?';
const name = getPokemonName(pokemon.pokemon_id);
const formName = getFormName(pokemon.form);
// TODO: Add pokemon costume to notification
const genderIcon = getGenderIcon(pokemon.gender);
const title = `Found Pokemon: ${name}${pokemon.form > 0 ? ' (Form: ' + formName + ')' : ''}`;
const message = `IV: ${iv}% Lvl: ${pokemon.level || '?'} Gender: ${genderIcon}`;
const icon = getPokemonIcon(pokemon.pokemon_id, pokemon.form, 0, pokemon.gender, pokemon.costume);
const iconUrl = `${availableIconStyles[selectedIconStyle].path}/${icon}.png`;
let notification = toastr.info(message, title, {
closeButton: true,
positionClass: 'toast-top-right',
preventDuplicates: true,
onclick: () => {
centerOnMap(pokemon.lat, pokemon.lon);
},
showDuration: '2000',
hideDuration: '1000',
timeOut: '6000',
extendedTimeOut: '1500',
showEasing: 'swing',
hideEasing: 'linear',
showMethod: 'fadeIn',
hideMethod: 'fadeOut',
});
notification.removeClass('toast-info');
notification.css({
'padding-left': '74px',
'background-image': `url('${iconUrl}')`,
'background-size': '48px',
'background-color': '#15151D', // TODO: Check dark mode?
});
};

const calculateIV = (pokemon) => {
return ((pokemon.atk_iv + pokemon.def_iv + pokemon.sta_iv) / .45).toFixed(2);
};

// MARK: - Init Filter

function populateImage (row, type, set, meta) {
Expand Down Expand Up @@ -7340,6 +7413,9 @@ function loadFilterSettings (e) {
showLevel51Stats = obj.level51_stats;
store('level51_stats', showLevel51Stats);

showPokemonNotifications = obj.show_pokemon_notifications;
store('show_pokemon_notifications', showPokemonNotifications);

if (showGyms) {
$('#show-gyms').addClass('active');
$('#hide-gyms').removeClass('active');
Expand Down