From cb09b402ab8636ed26a8ab8ff1ad1749d9e9e7f6 Mon Sep 17 00:00:00 2001 From: TurtIeSocks <58572875+TurtIeSocks@users.noreply.github.com> Date: Mon, 2 May 2022 23:33:05 -0400 Subject: [PATCH 1/2] Various Things - Fix some rendering issues on client side --- src/components/Container.jsx | 10 ++++++---- src/components/Map.jsx | 27 +++++++++++---------------- src/components/ReactRouter.jsx | 11 +++++++++-- src/components/layout/auth/Auth.jsx | 4 ++-- src/hooks/useConfig.js | 9 +++++++-- src/hooks/useGenerate.js | 8 ++++---- src/hooks/useRefresh.js | 20 +++++++++++++------- src/hooks/useStore.js | 2 ++ 8 files changed, 54 insertions(+), 37 deletions(-) diff --git a/src/components/Container.jsx b/src/components/Container.jsx index bd3d3d77f..46dbfbfa9 100644 --- a/src/components/Container.jsx +++ b/src/components/Container.jsx @@ -1,12 +1,14 @@ import React from 'react' import { MapContainer } from 'react-leaflet' -import { useStore } from '@hooks/useStore' + +import useGenerate from '@hooks/useGenerate' +import useRefresh from '@hooks/useRefresh' import Map from './Map' -export default function Container({ serverSettings, params }) { - const location = useStore(state => state.location) - const zoom = useStore(state => state.zoom) +export default function Container({ serverSettings, params, location, zoom }) { + useGenerate() + useRefresh() return ( state.ui) const staticFilters = useStatic(state => state.filters) const setExcludeList = useStatic(state => state.setExcludeList) + const active = useStatic(state => state.active) + const setActive = useStatic(state => state.setActive) const filters = useStore(state => state.filters) const settings = useStore(state => state.settings) @@ -69,15 +69,12 @@ export default function Map({ serverSettings: const [manualParams, setManualParams] = useState(params) const [error, setError] = useState('') const [windowState, setWindowState] = useState(true) - const [active, setActive] = useState(true) const [lc] = useState(L.control.locate({ position: 'bottomright', icon: 'fas fa-location-arrow', keepCurrentZoomLevel: true, setView: 'untilPan', })) - const startFetching = useRefresh(active) - useGenerate() const onMove = useCallback((latLon) => { const newCenter = latLon || map.getCenter() @@ -86,14 +83,18 @@ export default function Map({ serverSettings: setIsNight(Utility.nightCheck(newCenter.lat, newCenter.lng)) }, [map]) - const tileServer = useMemo(() => getTileServer(tileServers, settings, isNight), [settings.tileServers]) + const tileServer = useMemo(() => getTileServer(tileServers, settings, isNight), [isNight, settings.tileServers]) + + const onFocus = () => setWindowState(true) + + const onBlur = () => setWindowState(false) useEffect(() => { - window.addEventListener('focus', () => setWindowState(true)) - window.addEventListener('blur', () => setWindowState(false)) + window.addEventListener('focus', onFocus) + window.addEventListener('blur', onBlur) return () => { - window.removeEventListener('focus', () => setWindowState(true)) - window.removeEventListener('blur', () => setWindowState(false)) + window.removeEventListener('focus', onFocus) + window.removeEventListener('blur', onBlur) } }, []) @@ -114,12 +115,6 @@ export default function Map({ serverSettings: } }, [settings.navigationControls]) - useEffect(() => { - if (active) { - startFetching() - } - }, [active]) - return ( <> + const authRoute = ( + + ) return ( diff --git a/src/components/layout/auth/Auth.jsx b/src/components/layout/auth/Auth.jsx index a5aaf4e1d..bc029301e 100644 --- a/src/components/layout/auth/Auth.jsx +++ b/src/components/layout/auth/Auth.jsx @@ -5,7 +5,7 @@ import Container from '../../Container' import Login from './Login' import WebhookQuery from '../../WebhookQuery' -export default function Auth({ serverSettings, getServerSettings }) { +export default function Auth({ serverSettings, getServerSettings, location, zoom }) { const params = useParams() if (serverSettings.error) { @@ -38,6 +38,6 @@ export default function Auth({ serverSettings, getServerSettings }) { ) } return ( - + ) } diff --git a/src/hooks/useConfig.js b/src/hooks/useConfig.js index 540f8555d..a89ce07c0 100644 --- a/src/hooks/useConfig.js +++ b/src/hooks/useConfig.js @@ -139,7 +139,12 @@ export default function useConfig(serverSettings, paramLocation) { return updatePositionState([serverSettings.config.map.startLat, serverSettings.config.map.startLon], 'location') } - setZoom(updatePositionState(serverSettings.config.map.startZoom, 'zoom')) + const startLocation = getStartLocation() + const zoom = updatePositionState(serverSettings.config.map.startZoom, 'zoom') - setIsNight(Utility.nightCheck(...getStartLocation())) + setZoom(zoom) + + setIsNight(Utility.nightCheck(...startLocation)) + + return { location: startLocation, zoom } } diff --git a/src/hooks/useGenerate.js b/src/hooks/useGenerate.js index 8904945a7..4012c8cd9 100644 --- a/src/hooks/useGenerate.js +++ b/src/hooks/useGenerate.js @@ -1,4 +1,4 @@ -import { useEffect, useCallback } from 'react' +import { useEffect } from 'react' import { useTranslation } from 'react-i18next' import genPokemon from '@services/filtering/genPokemon' @@ -9,9 +9,9 @@ import { useStatic } from '@hooks/useStore' export default function useGenerate() { const { t } = useTranslation() - const { pokemon } = useStatic(useCallback(s => s.masterfile, [])) - const { gyms, pokestops } = useStatic(useCallback(s => s.filters, [])) - const staticMenus = useStatic(useCallback(s => s.menus, [])) + const { pokemon } = useStatic(s => s.masterfile) + const { gyms, pokestops } = useStatic(s => s.filters) + const staticMenus = useStatic(s => s.menus) const setMenuFilters = useStatic(s => s.setMenuFilters) useEffect(() => { diff --git a/src/hooks/useRefresh.js b/src/hooks/useRefresh.js index 6858762a8..493ee7f2c 100644 --- a/src/hooks/useRefresh.js +++ b/src/hooks/useRefresh.js @@ -1,21 +1,29 @@ -import { useLazyQuery } from '@apollo/client' +import { useQuery } from '@apollo/client' import getAvailable from '@services/queries/available' import { useEffect } from 'react' import { useStatic } from './useStore' -export default function useRefresh(active) { +export default function useRefresh() { const setAvailable = useStatic(s => s.setAvailable) const setMasterfile = useStatic(s => s.setMasterfile) const setStaticFilters = useStatic(s => s.setFilters) + const active = useStatic(s => s.active) - const [startFetching, { data }] = useLazyQuery(getAvailable, { + const { data, stopPolling, startPolling } = useQuery(getAvailable, { variables: { version: inject.VERSION }, fetchPolicy: active ? 'network-only' : 'cache-only', - pollInterval: 1000 * 60 * 10, - skip: !active, + pollInterval: 1000 * 60 * 60, }) + useEffect(() => { + if (active) { + startPolling() + } else { + stopPolling() + } + }, [active]) + useEffect(() => { if (data?.available) { const { masterfile, filters, ...rest } = data.available @@ -24,6 +32,4 @@ export default function useRefresh(active) { setStaticFilters(filters) } }, [data]) - - return startFetching } diff --git a/src/hooks/useStore.js b/src/hooks/useStore.js index 6f148d5ec..7f1520062 100644 --- a/src/hooks/useStore.js +++ b/src/hooks/useStore.js @@ -54,6 +54,8 @@ export const useStore = create(persist( )) export const useStatic = create(set => ({ + active: true, + setActive: (active) => set({ active }), auth: { discord: true, loggedIn: false, perms: {} }, setAuth: (auth) => set({ auth }), config: undefined, From c8258081388e3588d3edf5e57276ed9e81734827 Mon Sep 17 00:00:00 2001 From: TurtIeSocks <58572875+TurtIeSocks@users.noreply.github.com> Date: Mon, 2 May 2022 23:36:40 -0400 Subject: [PATCH 2/2] Backend maintenance - Add some configurable values for generating all possible desirable filters - Add some more available-based filter generation as a backup - Query for teams/slots during gym available - Don't set event timers if querying upon session init --- .../configs/custom-environment-variables.json | 54 ++++++++++++++++--- server/src/configs/default.json | 42 ++++++++++++++- server/src/models/Gym.js | 39 ++++++++++---- server/src/services/EventManager.js | 32 ++++++----- .../defaultFilters/buildDefaultFilters.js | 2 +- .../src/services/defaultFilters/buildGyms.js | 27 ++++++---- .../services/defaultFilters/buildPokemon.js | 2 +- .../services/defaultFilters/buildPokestops.js | 35 +++++++++--- 8 files changed, 181 insertions(+), 52 deletions(-) diff --git a/server/src/configs/custom-environment-variables.json b/server/src/configs/custom-environment-variables.json index 50aa92351..36b4896e8 100644 --- a/server/src/configs/custom-environment-variables.json +++ b/server/src/configs/custom-environment-variables.json @@ -163,6 +163,10 @@ "hideOldPokestops": { "__name": "API_HIDE_OLD_POKESTOPS", "__format": "boolean" + }, + "fetchTimeoutMs": { + "__name": "API_FETCH_TIMEOUT_MS", + "__format": "number" } }, "multiDomains": { @@ -621,6 +625,18 @@ "gymBadges": { "__name": "DEFAULT_FILTERS_GYMS_GYM_BADGES", "__format": "boolean" + }, + "baseRaidTiers": { + "__name": "DEFAULT_FILTERS_GYMS_BASE_RAID_TIERS", + "__format": "json" + }, + "baseTeamIds": { + "__name": "DEFAULT_FILTERS_GYMS_BASE_TEAM_IDS", + "__format": "json" + }, + "baseGymSlotAmounts": { + "__name": "DEFAULT_FILTERS_GYMS_BASE_GYM_SLOT_AMOUNTS", + "__format": "json" } }, "nests": { @@ -686,6 +702,36 @@ "allInvasions": { "__name": "DEFAULT_FILTERS_POKESTOPS_ALL_INVASIONS", "__format": "boolean" + }, + "rewardTypes": { + "__name": "DEFAULT_FILTERS_POKESTOPS_REWARD_TYPES", + "__format": "boolean" + }, + "baseMegaEnergyAmounts": { + "__name": "DEFAULT_FILTERS_POKESTOPS_BASE_MEGA_ENERGY_AMOUNTS", + "__format": "json" + }, + "baseLureIds": { + "__name": "DEFAULT_FILTERS_POKESTOPS_BASE_LURE_IDS", + "__format": "json" + }, + "stardust": { + "min": { + "__name": "DEFAULT_FILTERS_POKESTOPS_STARDUST_MIN", + "__format": "number" + }, + "max": { + "__name": "DEFAULT_FILTERS_POKESTOPS_STARDUST_MAX", + "__format": "number" + }, + "interval": { + "__name": "DEFAULT_FILTERS_POKESTOPS_STARDUST_INTERVAL", + "__format": "number" + }, + "enabled": { + "__name": "DEFAULT_FILTERS_POKESTOPS_STARDUST_ENABLED", + "__format": "boolean" + } } }, "pokemon": { @@ -782,14 +828,6 @@ "maxConnections": { "__name": "DATABASE_SETTINGS_MAX_CONNECTIONS", "__format": "number" - }, - "startupDelayMs": { - "__name": "DATABASE_SETTINGS_STARTUP_DELAY_MS", - "__format": "number" - }, - "availableRetryCount": { - "__name": "DATABASE_SETTINGS_AVAILABLE_RETRY_COUNT", - "__format": "number" } }, "schemas": { diff --git a/server/src/configs/default.json b/server/src/configs/default.json index 360e196b8..9581167d9 100644 --- a/server/src/configs/default.json +++ b/server/src/configs/default.json @@ -277,7 +277,27 @@ "raids": true, "eggs": true, "pokemon": true, - "gymBadges": false + "gymBadges": false, + "baseRaidTiers": [ + 1, + 3, + 5, + 6 + ], + "baseTeamIds": [ + 0, + 1, + 2, + 3 + ], + "baseGymSlotAmounts": [ + 1, + 2, + 3, + 4, + 5, + 6 + ] }, "nests": { "enabled": false, @@ -300,7 +320,25 @@ "candy": true, "pokemon": true, "invasions": false, - "allInvasions": true + "allInvasions": true, + "rewardTypes": false, + "baseMegaEnergyAmounts": [ + 10, + 20 + ], + "baseLureIds": [ + 501, + 502, + 503, + 504, + 505 + ], + "stardust": { + "min": 100, + "max": 2000, + "interval": 100, + "enabled": true + } }, "pokemon": { "enabled": false, diff --git a/server/src/models/Gym.js b/server/src/models/Gym.js index cece66e5a..94bd06fcf 100644 --- a/server/src/models/Gym.js +++ b/server/src/models/Gym.js @@ -6,6 +6,7 @@ const { Event } = require('../services/initialization') const getAreaSql = require('../services/functions/getAreaSql') const { api: { searchResultsLimit, queryLimits, gymValidDataLimit, hideOldGyms }, + defaultFilters: { gyms: { baseTeamIds, baseGymSlotAmounts } }, } = require('../services/config') const Badge = require('./Badge') @@ -92,7 +93,7 @@ module.exports = class Gym extends Model { case 't': teams.push(gym.slice(1).split('-')[0]); break case 'g': slots.push({ team: gym.slice(1).split('-')[0], - slots: 6 - gym.slice(1).split('-')[1], + slots: baseGymSlotAmounts.length - gym.slice(1).split('-')[1], }); break default: { const [id, form] = gym.split('-') @@ -103,11 +104,7 @@ module.exports = class Gym extends Model { }) const finalTeams = [] - const finalSlots = { - 1: [], - 2: [], - 3: [], - } + const finalSlots = Object.fromEntries(baseTeamIds.map(team => [team, []])) teams.forEach(team => { let slotCount = 0 @@ -117,7 +114,7 @@ module.exports = class Gym extends Model { finalSlots[team].push(+slot.slots) } }) - if (slotCount === 6 || team == 0) { + if (slotCount === baseGymSlotAmounts.length || team == 0) { delete finalSlots[team] finalTeams.push(+team) } @@ -270,15 +267,35 @@ module.exports = class Gym extends Model { isMad ? 'level' : 'raid_level', ]) .orderBy(isMad ? 'pokemon_id' : 'raid_pokemon_id', 'asc') - if (results.length === 0) { - return fetchRaids() + const teamResults = await this.query() + .select([ + 'team_id AS team', + isMad ? 'slots_available AS slots' : 'availble_slots AS slots', + ]) + .groupBy([ + 'team_id', + isMad ? 'slots_available' : 'availble_slots', + ]) + .then((r) => { + const unique = new Set() + r.forEach(result => { + if (result.slots) { + unique.add(`g${result.team}-${result.slots}`) + } else { + unique.add(`t${result.team}-0`) + } + }) + return [...unique] + }) + if (!results.length) { + return [...teamResults, ...await fetchRaids()] } - return results.flatMap(result => { + return [...teamResults, ...results.flatMap(result => { if (result.raid_pokemon_id) { return `${result.raid_pokemon_id}-${result.raid_pokemon_form}` } return [`e${result.raid_level}`, `r${result.raid_level}`] - }) + })] } static async search(perms, args, { isMad }, distance) { diff --git a/server/src/services/EventManager.js b/server/src/services/EventManager.js index e0f94a71d..d91cf0599 100644 --- a/server/src/services/EventManager.js +++ b/server/src/services/EventManager.js @@ -22,18 +22,26 @@ module.exports = class EventManager { } setTimers(config, Db, Pvp) { - setInterval(async () => { - this.available.gyms = await Db.getAvailable('Gym') - }, 1000 * 60 * 60 * (config.api.queryUpdateHours.raids || 1)) - setInterval(async () => { - this.available.nests = await Db.getAvailable('Nest') - }, 1000 * 60 * 60 * (config.api.queryUpdateHours.nests || 6)) - setInterval(async () => { - this.available.pokemon = await Db.getAvailable('Pokemon') - }, 1000 * 60 * 60 * (config.api.queryUpdateHours.pokemon || 1)) - setInterval(async () => { - this.available.pokestops = await Db.getAvailable('Pokestop') - }, 1000 * 60 * 60 * (config.api.queryUpdateHours.quests || 3)) + if (!config.api.queryOnSessionInit.raids) { + setInterval(async () => { + this.available.gyms = await Db.getAvailable('Gym') + }, 1000 * 60 * 60 * (config.api.queryUpdateHours.raids || 1)) + } + if (!config.api.queryOnSessionInit.nests) { + setInterval(async () => { + this.available.nests = await Db.getAvailable('Nest') + }, 1000 * 60 * 60 * (config.api.queryUpdateHours.nests || 6)) + } + if (!config.api.queryOnSessionInit.pokemon) { + setInterval(async () => { + this.available.pokemon = await Db.getAvailable('Pokemon') + }, 1000 * 60 * 60 * (config.api.queryUpdateHours.pokemon || 1)) + } + if (!config.api.queryOnSessionInit.quests) { + setInterval(async () => { + this.available.pokestops = await Db.getAvailable('Pokestop') + }, 1000 * 60 * 60 * (config.api.queryUpdateHours.quests || 3)) + } setInterval(async () => { await this.getUicons(config.icons.styles) }, 1000 * 60 * 60 * (config.icons.cacheHrs || 3)) diff --git a/server/src/services/defaultFilters/buildDefaultFilters.js b/server/src/services/defaultFilters/buildDefaultFilters.js index 146d43e30..03d4d256d 100644 --- a/server/src/services/defaultFilters/buildDefaultFilters.js +++ b/server/src/services/defaultFilters/buildDefaultFilters.js @@ -48,7 +48,7 @@ module.exports = function buildDefault(perms, available) { invasions: perms.invasions ? defaultFilters.pokestops.invasions : undefined, arEligible: perms.pokestops ? false : undefined, filter: { - ...buildPokestops(perms, defaultFilters.pokestops), + ...buildPokestops(perms, defaultFilters.pokestops, available), ...pokemon.quests, }, } : undefined, diff --git a/server/src/services/defaultFilters/buildGyms.js b/server/src/services/defaultFilters/buildGyms.js index 955de95e9..abf8b9455 100644 --- a/server/src/services/defaultFilters/buildGyms.js +++ b/server/src/services/defaultFilters/buildGyms.js @@ -4,24 +4,33 @@ module.exports = function buildGyms(perms, defaults, available) { const gymFilters = {} if (perms.gyms) { - for (let i = 0; i <= 3; i += 1) { - gymFilters[`t${i}-0`] = new GenericFilter(defaults.allGyms) + defaults.baseTeamIds.forEach((team, i) => { + gymFilters[`t${team}-0`] = new GenericFilter(defaults.allGyms) if (i) { - for (let j = 1; j <= 6; j += 1) { - gymFilters[`g${i}-${j}`] = new GenericFilter(defaults.allGyms) - } + defaults.baseGymSlotAmounts.forEach(slot => { + gymFilters[`g${team}-${slot}`] = new GenericFilter(defaults.allGyms) + }) } - } + }) } if (perms.raids) { - available.gyms.forEach(avail => { + defaults.baseRaidTiers.forEach(tier => { + gymFilters[`e${tier}`] = new GenericFilter(defaults.eggs) + gymFilters[`r${tier}`] = new GenericFilter(defaults.raids) + }) + } + available.gyms.forEach(avail => { + if (perms.gyms && (avail.startsWith('t') || avail.startsWith('g'))) { + gymFilters[avail] = new GenericFilter(defaults.allGyms) + } + if (perms.raids) { if (avail.startsWith('e')) { gymFilters[avail] = new GenericFilter(defaults.eggs) } if (avail.startsWith('r')) { gymFilters[avail] = new GenericFilter(defaults.raids) } - }) - } + } + }) return gymFilters } diff --git a/server/src/services/defaultFilters/buildPokemon.js b/server/src/services/defaultFilters/buildPokemon.js index 3d9fb9235..98fea8c80 100644 --- a/server/src/services/defaultFilters/buildPokemon.js +++ b/server/src/services/defaultFilters/buildPokemon.js @@ -9,7 +9,7 @@ module.exports = function buildPokemon(defaults, base, custom, available) { quests: { global: new GenericFilter() }, nests: { global: new GenericFilter() }, } - const energyAmounts = new Set(['10', '20', ...available.pokestops + const energyAmounts = new Set([...defaults.pokestops.baseMegaEnergyAmounts, ...available.pokestops .filter((e) => e.startsWith('m')) .map((e) => e.split('-')[1])]) diff --git a/server/src/services/defaultFilters/buildPokestops.js b/server/src/services/defaultFilters/buildPokestops.js index f8d2c1aea..a22fdc8f4 100644 --- a/server/src/services/defaultFilters/buildPokestops.js +++ b/server/src/services/defaultFilters/buildPokestops.js @@ -1,32 +1,51 @@ const { GenericFilter } = require('../../models/index') const { Event } = require('../initialization') -module.exports = function buildPokestops(perms, defaults) { +module.exports = function buildPokestops(perms, defaults, available) { const quests = { s0: new GenericFilter() } if (perms.lures) { - for (let i = 1; i <= 5; i += 1) { - quests[`l50${i}`] = new GenericFilter(defaults.lures) - } + defaults.baseLureIds.forEach(lure => { + quests[`l${lure}`] = new GenericFilter(defaults.lures) + }) } if (perms.quests) { Object.keys(Event.masterfile.items).forEach(item => { quests[`q${item}`] = new GenericFilter(defaults.items) }) - for (let i = 200; i <= 2000; i += 100) { - quests[`d${i}`] = new GenericFilter(defaults.items) + for (let i = defaults.stardust.min; i <= defaults.stardust.max; i += defaults.stardust.interval) { + quests[`d${i}`] = new GenericFilter(defaults.stardust.enabled) } Object.keys(Event.masterfile.questRewardTypes).forEach(type => { if (type !== '0') { - quests[`u${type}`] = new GenericFilter() + quests[`u${type}`] = new GenericFilter(defaults.rewardTypes) } }) } if (perms.invasions) { Object.keys(Event.invasions).forEach(type => { - if (type != 0) { + if (type !== '0') { quests[`i${type}`] = new GenericFilter(defaults.allInvasions) } }) } + available.pokestops.forEach(avail => { + if (perms.lures && avail.startsWith('l')) { + quests[avail] = new GenericFilter(defaults.lures) + } + if (perms.quests) { + if (avail.startsWith('q')) { + quests[avail] = new GenericFilter(defaults.items) + } + if (avail.startsWith('d')) { + quests[avail] = new GenericFilter(defaults.stardust.enabled) + } + if (avail.startsWith('u')) { + quests[avail] = new GenericFilter(defaults.rewardTypes) + } + } + if (perms.invasions && avail.startsWith('i')) { + quests[avail] = new GenericFilter(defaults.allInvasions) + } + }) return quests }