From 80d5b7403f0644b635c326464bf01a55eef98d36 Mon Sep 17 00:00:00 2001 From: Derick M <58572875+TurtIeSocks@users.noreply.github.com> Date: Tue, 8 Nov 2022 20:31:12 -0500 Subject: [PATCH] event stop support - Adds event_stop filter, requires pokestops perms - Adds switch to toggle timers for event stops - New locale keys --- public/base-locales/en.json | 6 ++- server/src/configs/default.json | 2 + server/src/models/Pokestop.js | 49 ++++++++++++++++--- .../defaultFilters/buildDefaultFilters.js | 3 ++ server/src/services/ui/clientOptions.js | 1 + src/components/Map.jsx | 1 + src/components/markers/pokestop.jsx | 16 +++--- src/components/popups/Pokestop.jsx | 7 ++- src/components/tiles/Pokestop.jsx | 17 ++++++- src/services/Query.js | 4 +- 10 files changed, 87 insertions(+), 19 deletions(-) diff --git a/public/base-locales/en.json b/public/base-locales/en.json index 958786ec5..60de2b8ae 100644 --- a/public/base-locales/en.json +++ b/public/base-locales/en.json @@ -558,5 +558,7 @@ "seen_nearby_cell": "Seen in this Cell", "seen_lure_encounter": "Lure Encounter", "seen_lure_wild": "Lure Spawn", - "seen_wild": "Wild Spawn" -} + "seen_wild": "Wild Spawn", + "event_stops": "Event Stops", + "event_stop_timers": "Event Stop Timers" +} \ No newline at end of file diff --git a/server/src/configs/default.json b/server/src/configs/default.json index 1e3540e5a..cc548d46b 100644 --- a/server/src/configs/default.json +++ b/server/src/configs/default.json @@ -300,6 +300,7 @@ "clustering": true, "invasionTimers": false, "lureTimers": false, + "eventStopTimers": false, "interactionRanges": false, "lureRange": false, "madQuestText": false, @@ -419,6 +420,7 @@ "levels": "all", "lures": true, "quests": true, + "eventStops": false, "questSet": "both", "items": true, "megaEnergy": true, diff --git a/server/src/models/Pokestop.js b/server/src/models/Pokestop.js index f042e6766..21a2446b6 100644 --- a/server/src/models/Pokestop.js +++ b/server/src/models/Pokestop.js @@ -70,6 +70,7 @@ module.exports = class Pokestop extends Model { onlyInvasions, onlyArEligible, onlyAllPokestops, + onlyEventStops, onlyAreas = [], }, ts, @@ -515,11 +516,24 @@ module.exports = class Pokestop extends Model { ar.where(isMad ? 'is_ar_scan_eligible' : 'ar_scan_eligible', 1) }) } + if (onlyEventStops && pokestopPerms) { + stops.orWhere((event) => { + event + .where('display_type', 7) + .andWhere('character', 0) + .andWhere( + multiInvasionMs ? 'expiration_ms' : 'expiration', + '>=', + safeTs * (multiInvasionMs ? 1000 : 1), + ) + }) + } }) } else if (onlyLevels !== 'all' && hasPowerUp) { query.andWhere('power_up_level', onlyLevels) } const results = await query + const normalized = isMad ? this.mapMAD(results, safeTs) : this.mapRDM(results, safeTs) @@ -571,16 +585,25 @@ module.exports = class Pokestop extends Model { 'power_up_level', 'power_up_end_timestamp', ]) + if (filters.onlyEventStops) { + filtered.invasions = pokestop.invasions.filter( + (invasion) => !invasion.grunt_type, + ) + } } if ( perms.invasions && (filters.onlyAllPokestops || filters.onlyInvasions) ) { - filtered.invasions = filters.onlyAllPokestops - ? pokestop.invasions - : pokestop.invasions.filter( - (invasion) => filters[`i${invasion.grunt_type}`], - ) + filtered.invasions = [ + ...(Array.isArray(filtered.invasions) ? filtered.invasions : []), + ...(filters.onlyAllPokestops + ? pokestop.invasions + : pokestop.invasions.filter( + (invasion) => + invasion.grunt_type && filters[`i${invasion.grunt_type}`], + )), + ] } if ( perms.lures && @@ -715,7 +738,10 @@ module.exports = class Pokestop extends Model { } }) } - if (invasion.grunt_type && invasion.incident_expire_timestamp >= ts) { + if ( + typeof invasion.grunt_type === 'number' && + invasion.incident_expire_timestamp >= ts + ) { filtered[result.id].invasions.push(invasion) } filtered[result.id].quests.push(quest) @@ -755,7 +781,10 @@ module.exports = class Pokestop extends Model { if (altQuest.quest_reward_type) { filtered[result.id].quests.push(altQuest) } - if (invasion.grunt_type && invasion.incident_expire_timestamp >= ts) { + if ( + typeof invasion.grunt_type === 'number' && + invasion.incident_expire_timestamp >= ts + ) { filtered[result.id].invasions.push(invasion) } } @@ -1070,11 +1099,17 @@ module.exports = class Pokestop extends Model { } else { queries.invasions = this.query() .distinct(isMad ? 'incident_grunt_type AS grunt_type' : 'grunt_type') + .where( + isMad ? 'incident_grunt_type AS grunt_type' : 'grunt_type', + '>', + 0, + ) .where( isMad ? 'incident_expiration' : 'incident_expire_timestamp', '>=', isMad ? this.knex().fn.now() : ts, ) + .orderBy('grunt_type') } // invasions diff --git a/server/src/services/defaultFilters/buildDefaultFilters.js b/server/src/services/defaultFilters/buildDefaultFilters.js index a20c5a3c8..bb4967f53 100644 --- a/server/src/services/defaultFilters/buildDefaultFilters.js +++ b/server/src/services/defaultFilters/buildDefaultFilters.js @@ -64,6 +64,9 @@ module.exports = function buildDefault(perms, available, dbModels) { ? defaultFilters.pokestops.levels : undefined, lures: perms.lures ? defaultFilters.pokestops.lures : undefined, + eventStops: perms.pokestops + ? defaultFilters.pokestops.eventStops + : undefined, quests: perms.quests ? defaultFilters.pokestops.quests : undefined, showQuestSet: defaultFilters.pokestops.questSet, invasions: perms.invasions diff --git a/server/src/services/ui/clientOptions.js b/server/src/services/ui/clientOptions.js index a1bb162f0..7a788e4a7 100644 --- a/server/src/services/ui/clientOptions.js +++ b/server/src/services/ui/clientOptions.js @@ -26,6 +26,7 @@ module.exports = function clientOptions(perms) { clustering: { type: 'bool', perm: ['pokestops', 'quests', 'invasions'] }, invasionTimers: { type: 'bool', perm: ['invasions'] }, lureTimers: { type: 'bool', perm: ['lures'] }, + eventStopTimers: { type: 'bool', perm: ['pokestops'] }, interactionRanges: { type: 'bool', perm: ['pokestops'] }, lureRange: { type: 'bool', perm: ['lures'] }, hasQuestIndicator: { type: 'bool', perm: ['quests'] }, diff --git a/src/components/Map.jsx b/src/components/Map.jsx index b84cb9177..1f3fa1a13 100644 --- a/src/components/Map.jsx +++ b/src/components/Map.jsx @@ -203,6 +203,7 @@ export default function Map({ (filters[category].lures && value.lures) || (filters[category].invasions && value.invasions) || (filters[category].quests && value.quests) || + (filters[category].eventStops && value.eventStops) || (filters[category].arEligible && value.arEligible)) && !webhookMode ) { diff --git a/src/components/markers/pokestop.jsx b/src/components/markers/pokestop.jsx index ff755de43..beaf215fe 100644 --- a/src/components/markers/pokestop.jsx +++ b/src/components/markers/pokestop.jsx @@ -42,12 +42,16 @@ export default function stopMarker( if (hasInvasion) { const { invasions } = pokestop invasions.forEach((invasion) => { - filterId = `i${invasion.grunt_type}` - invasionIcons.unshift(Icons.getInvasions(invasion.grunt_type)) - invasionSizes.unshift(Icons.getSize('invasion', filters.filter[filterId])) - popupYOffset += rewardMod.offsetY - 1 - popupX += invasionMod.popupX - popupY += invasionMod.popupY + if (invasion.grunt_type) { + filterId = `i${invasion.grunt_type}` + invasionIcons.unshift(Icons.getInvasions(invasion.grunt_type)) + invasionSizes.unshift( + Icons.getSize('invasion', filters.filter[filterId]), + ) + popupYOffset += rewardMod.offsetY - 1 + popupX += invasionMod.popupX + popupY += invasionMod.popupY + } }) } if (hasQuest && !(hasInvasion && invasionMod?.removeQuest)) { diff --git a/src/components/popups/Pokestop.jsx b/src/components/popups/Pokestop.jsx index b361f3ca8..1c4345f5b 100644 --- a/src/components/popups/Pokestop.jsx +++ b/src/components/popups/Pokestop.jsx @@ -48,7 +48,10 @@ export default function PokestopPopup({ ) }, []) - const plainPokestop = !hasLure && !hasQuest && !hasInvasion + const hasEventInvasion = invasions?.some((invasion) => !invasion.grunt_type) + + const plainPokestop = + !hasLure && !hasQuest && !hasInvasion && !hasEventInvasion return ( @@ -142,7 +145,7 @@ export default function PokestopPopup({ /> )} - {hasInvasion && ( + {(hasInvasion || hasEventInvasion) && ( <> {(hasQuest || hasLure) && ( diff --git a/src/components/tiles/Pokestop.jsx b/src/components/tiles/Pokestop.jsx index a59059b0b..30b8ecc2b 100644 --- a/src/components/tiles/Pokestop.jsx +++ b/src/components/tiles/Pokestop.jsx @@ -34,6 +34,7 @@ const PokestopTile = ({ item.invasions && item.invasions.some( (invasion) => + invasion.grunt_type && !excludeList.includes(`i${invasion.grunt_type}`) && invasion.incident_expire_timestamp > newTs, ) @@ -50,6 +51,17 @@ const PokestopTile = ({ if ((showTimer || userSettings.lureTimers) && hasLure) { timers.push(item.lure_expire_timestamp) } + if ( + (showTimer || userSettings.eventStopTimers) && + !hasInvasion && + item.invasions?.length + ) { + item.invasions.forEach((invasion) => { + if (!invasion.grunt_type) { + timers.push(invasion.incident_expire_timestamp) + } + }) + } useMarkerTimer( timers.length ? Math.min(...timers) : null, @@ -66,7 +78,10 @@ const PokestopTile = ({ (hasQuest && perms.quests) || (hasLure && perms.lures) || (hasInvasion && perms.invasions) || - ((filters.allPokestops || item.ar_scan_eligible) && perms.allPokestops), + ((filters.allPokestops || + item.ar_scan_eligible || + filters.eventStops) && + perms.allPokestops), ) && ( { diff --git a/src/services/Query.js b/src/services/Query.js index 256301ac9..60c2adfff 100644 --- a/src/services/Query.js +++ b/src/services/Query.js @@ -64,7 +64,9 @@ export default class Query { const permObj = { Lures: filters.lures && perms.lures, Quests: filters.quests && perms.quests, - Invasions: filters.invasions && perms.invasions, + Invasions: + (filters.invasions && perms.invasions) || + (filters.eventStops && perms.allPokestops), } let query = 'get'