Skip to content

Commit 5cd5be0

Browse files
authored
feat: persistent popups
Merge pull request #1135 from Mygod/persistent-popup
1 parent eea05ff commit 5cd5be0

File tree

21 files changed

+480
-135
lines changed

21 files changed

+480
-135
lines changed

server/src/models/Gym.js

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ const config = require('@rm/config')
99
const { getAreaSql } = require('../utils/getAreaSql')
1010
const { state } = require('../services/state')
1111

12+
const { applyManualIdFilter } = require('../utils/manualFilter')
13+
1214
const coreFields = [
1315
'id',
1416
'name',
@@ -83,6 +85,7 @@ class Gym extends Model {
8385
onlyGymBadges,
8486
onlyBadge,
8587
onlyAreas = [],
88+
onlyManualId,
8689
} = args.filters
8790
const ts = Math.floor(Date.now() / 1000)
8891
const query = this.query()
@@ -130,9 +133,22 @@ class Gym extends Model {
130133
} else if (hideOldGyms) {
131134
query.where('updated', '>', ts - gymValidDataLimit * 86400)
132135
}
133-
query
134-
.whereBetween(isMad ? 'latitude' : 'lat', [args.minLat, args.maxLat])
135-
.andWhereBetween(isMad ? 'longitude' : 'lon', [args.minLon, args.maxLon])
136+
const latCol = isMad ? 'latitude' : 'lat'
137+
const lonCol = isMad ? 'longitude' : 'lon'
138+
const idCol = isMad ? 'gym.gym_id' : 'id'
139+
140+
applyManualIdFilter(query, {
141+
manualId: onlyManualId,
142+
latColumn: latCol,
143+
lonColumn: lonCol,
144+
idColumn: idCol,
145+
bounds: {
146+
minLat: args.minLat,
147+
maxLat: args.maxLat,
148+
minLon: args.minLon,
149+
maxLon: args.maxLon,
150+
},
151+
})
136152
Gym.onlyValid(query, isMad)
137153

138154
const raidBosses = new Set()

server/src/models/Nest.js

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const config = require('@rm/config')
55

66
const { state } = require('../services/state')
77
const { getAreaSql } = require('../utils/getAreaSql')
8+
const { applyManualIdFilter } = require('../utils/manualFilter')
89

910
/** @typedef {Nest & Partial<import("@rm/types").Nest>} FullNest */
1011

@@ -27,11 +28,14 @@ class Nest extends Model {
2728
static async getAll(perms, args, { polygon }) {
2829
const { areaRestrictions } = perms
2930
const { minLat, minLon, maxLat, maxLon, filters } = args
30-
const query = this.query()
31-
.select(['*', 'nest_id AS id'])
32-
// .whereNotNull('pokemon_id')
33-
.whereBetween('lat', [minLat, maxLat])
34-
.andWhereBetween('lon', [minLon, maxLon])
31+
const query = this.query().select(['*', 'nest_id AS id'])
32+
applyManualIdFilter(query, {
33+
manualId: filters.onlyManualId,
34+
latColumn: 'lat',
35+
lonColumn: 'lon',
36+
idColumn: 'nest_id',
37+
bounds: { minLat, maxLat, minLon, maxLon },
38+
})
3539

3640
const pokemon = []
3741
if (filters.onlyPokemon) {

server/src/models/Pokemon.js

Lines changed: 153 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ const config = require('@rm/config')
1414
const { getAreaSql } = require('../utils/getAreaSql')
1515
const { filterRTree } = require('../utils/filterRTree')
1616
const { fetchJson } = require('../utils/fetchJson')
17+
const {
18+
applyManualIdFilter,
19+
normalizeManualId,
20+
} = require('../utils/manualFilter')
1721
const {
1822
IV_CALC,
1923
LEVEL_CALC,
@@ -148,6 +152,10 @@ class Pokemon extends Model {
148152

149153
const query = this.query()
150154

155+
const manualIdFilter = normalizeManualId(args.filters.onlyManualId)
156+
157+
let manualId = manualIdFilter
158+
151159
const pokemonIds = []
152160
const pokemonForms = []
153161
Object.values(filterMap).forEach((filter) => {
@@ -169,75 +177,81 @@ class Pokemon extends Model {
169177
} else {
170178
query.select(['*', hasSize && !hasHeight ? 'size AS height' : 'size'])
171179
}
172-
query
173-
.where(
174-
isMad ? 'disappear_time' : 'expire_timestamp',
175-
'>=',
176-
isMad ? this.knex().fn.now() : ts,
177-
)
178-
.andWhereBetween(isMad ? 'pokemon.latitude' : 'lat', [
179-
args.minLat,
180-
args.maxLat,
181-
])
182-
.andWhereBetween(isMad ? 'pokemon.longitude' : 'lon', [
183-
args.minLon,
184-
args.maxLon,
185-
])
186-
.andWhere((ivOr) => {
187-
if (ivs || pvp) {
188-
if (globalFilter.filterKeys.size) {
189-
ivOr.andWhere((pkmn) => {
190-
const keys = globalFilter.keyArray
191-
for (let i = 0; i < keys.length; i += 1) {
192-
const key = keys[i]
193-
switch (key) {
194-
case 'xxs':
195-
case 'xxl':
196-
if (hasSize) {
197-
pkmn.orWhere('pokemon.size', key === 'xxl' ? 5 : 1)
198-
}
199-
break
200-
case 'gender':
201-
pkmn.andWhere('pokemon.gender', onlyIvOr[key])
202-
break
203-
case 'cp':
204-
case 'level':
205-
case 'atk_iv':
206-
case 'def_iv':
207-
case 'sta_iv':
208-
case 'iv':
209-
if (perms.iv) {
210-
pkmn.andWhereBetween(
211-
isMad ? MAD_KEY_MAP[key] : key,
212-
onlyIvOr[key],
213-
)
214-
}
215-
break
216-
default:
217-
if (
218-
perms.pvp &&
219-
BASE_KEYS.every((x) => !globalFilter.filterKeys.has(x))
220-
) {
221-
// doesn't return everything if only pvp stats for individual pokemon
222-
pkmn.whereNull('pokemon_id')
223-
}
224-
break
225-
}
180+
query.where(
181+
isMad ? 'disappear_time' : 'expire_timestamp',
182+
'>=',
183+
isMad ? this.knex().fn.now() : ts,
184+
)
185+
manualId = applyManualIdFilter(query, {
186+
manualId: manualIdFilter,
187+
latColumn: isMad ? 'pokemon.latitude' : 'lat',
188+
lonColumn: isMad ? 'pokemon.longitude' : 'lon',
189+
idColumn: isMad ? 'pokemon.encounter_id' : 'id',
190+
bounds: {
191+
minLat: args.minLat,
192+
maxLat: args.maxLat,
193+
minLon: args.minLon,
194+
maxLon: args.maxLon,
195+
},
196+
})
197+
query.andWhere((ivOr) => {
198+
if (ivs || pvp) {
199+
if (globalFilter.filterKeys.size) {
200+
ivOr.andWhere((pkmn) => {
201+
const keys = globalFilter.keyArray
202+
for (let i = 0; i < keys.length; i += 1) {
203+
const key = keys[i]
204+
switch (key) {
205+
case 'xxs':
206+
case 'xxl':
207+
if (hasSize) {
208+
pkmn.orWhere('pokemon.size', key === 'xxl' ? 5 : 1)
209+
}
210+
break
211+
case 'gender':
212+
pkmn.andWhere('pokemon.gender', onlyIvOr[key])
213+
break
214+
case 'cp':
215+
case 'level':
216+
case 'atk_iv':
217+
case 'def_iv':
218+
case 'sta_iv':
219+
case 'iv':
220+
if (perms.iv) {
221+
pkmn.andWhereBetween(
222+
isMad ? MAD_KEY_MAP[key] : key,
223+
onlyIvOr[key],
224+
)
225+
}
226+
break
227+
default:
228+
if (
229+
perms.pvp &&
230+
BASE_KEYS.every((x) => !globalFilter.filterKeys.has(x))
231+
) {
232+
// doesn't return everything if only pvp stats for individual pokemon
233+
pkmn.whereNull('pokemon_id')
234+
}
235+
break
226236
}
227-
})
228-
} else {
229-
ivOr.whereNull('pokemon_id')
230-
}
231-
ivOr.orWhereIn('pokemon_id', pokemonIds)
232-
ivOr.orWhereIn('pokemon.form', pokemonForms)
233-
}
234-
if (onlyZeroIv && ivs) {
235-
ivOr.orWhere(isMad ? raw(IV_CALC) : 'iv', 0)
236-
}
237-
if (onlyHundoIv && ivs) {
238-
ivOr.orWhere(isMad ? raw(IV_CALC) : 'iv', 100)
237+
}
238+
})
239+
} else {
240+
ivOr.whereNull('pokemon_id')
239241
}
240-
})
242+
ivOr.orWhereIn('pokemon_id', pokemonIds)
243+
ivOr.orWhereIn('pokemon.form', pokemonForms)
244+
}
245+
if (onlyZeroIv && ivs) {
246+
ivOr.orWhere(isMad ? raw(IV_CALC) : 'iv', 0)
247+
}
248+
if (onlyHundoIv && ivs) {
249+
ivOr.orWhere(isMad ? raw(IV_CALC) : 'iv', 100)
250+
}
251+
if (manualId !== null) {
252+
ivOr.orWhereIn(isMad ? 'pokemon.encounter_id' : 'id', [manualId])
253+
}
254+
})
241255
if (!getAreaSql(query, areaRestrictions, onlyAreas, isMad, 'pokemon')) {
242256
return []
243257
}
@@ -272,7 +286,7 @@ class Pokemon extends Model {
272286
filters.push({ iv: { min: 100, max: 100 }, pokemon: globalPokes })
273287
}
274288
/** @type {import("@rm/types").Pokemon[]} */
275-
const results = await this.evalQuery(
289+
let results = await this.evalQuery(
276290
mem ? `${mem}/api/pokemon/v2/scan` : null,
277291
mem
278292
? JSON.stringify({
@@ -293,6 +307,30 @@ class Pokemon extends Model {
293307
httpAuth,
294308
)
295309

310+
if (mem && manualId !== null) {
311+
const loadedIds = Array.isArray(results)
312+
? new Set(results.map((pkmn) => `${pkmn.id}`))
313+
: new Set()
314+
if (!loadedIds.has(`${manualId}`)) {
315+
const manualResult = await this.evalQuery(
316+
`${mem}/api/pokemon/id/${manualId}`,
317+
null,
318+
'GET',
319+
secret,
320+
httpAuth,
321+
).catch(() => null)
322+
if (manualResult) {
323+
results = Array.isArray(results)
324+
? [...results, manualResult]
325+
: [manualResult]
326+
}
327+
}
328+
}
329+
330+
if (!Array.isArray(results)) {
331+
results = []
332+
}
333+
296334
const finalResults = []
297335
const pvpResults = []
298336
const listOfIds = []
@@ -326,20 +364,23 @@ class Pokemon extends Model {
326364
if (isMad) {
327365
Pokemon.getMadSql(pvpQuery)
328366
}
329-
pvpQuery
330-
.where(
331-
isMad ? 'disappear_time' : 'expire_timestamp',
332-
'>=',
333-
isMad ? this.knex().fn.now() : ts,
334-
)
335-
.andWhereBetween(isMad ? 'pokemon.latitude' : 'lat', [
336-
args.minLat,
337-
args.maxLat,
338-
])
339-
.andWhereBetween(isMad ? 'pokemon.longitude' : 'lon', [
340-
args.minLon,
341-
args.maxLon,
342-
])
367+
pvpQuery.where(
368+
isMad ? 'disappear_time' : 'expire_timestamp',
369+
'>=',
370+
isMad ? this.knex().fn.now() : ts,
371+
)
372+
applyManualIdFilter(pvpQuery, {
373+
manualId,
374+
latColumn: isMad ? 'pokemon.latitude' : 'lat',
375+
lonColumn: isMad ? 'pokemon.longitude' : 'lon',
376+
idColumn: isMad ? 'pokemon.encounter_id' : 'id',
377+
bounds: {
378+
minLat: args.minLat,
379+
maxLat: args.maxLat,
380+
minLon: args.minLon,
381+
maxLon: args.maxLon,
382+
},
383+
})
343384
if (isMad && listOfIds.length) {
344385
pvpQuery.whereRaw(
345386
`pokemon.encounter_id NOT IN ( ${listOfIds.join(',')} )`,
@@ -643,6 +684,7 @@ class Pokemon extends Model {
643684
const { isMad, hasSize, hasHeight, mem, secret, httpAuth } = ctx
644685
const ts = Math.floor(Date.now() / 1000)
645686
const { filterMap, globalFilter } = this.getFilters(perms, args, ctx)
687+
const manualIdFilter = normalizeManualId(args.filters.onlyManualId)
646688
const queryLimits = config.getSafe('api.queryLimits')
647689

648690
if (!perms.iv && !perms.pvp) {
@@ -682,14 +724,25 @@ class Pokemon extends Model {
682724
) {
683725
return []
684726
}
685-
727+
const manualId = applyManualIdFilter(query, {
728+
manualId: manualIdFilter,
729+
latColumn: isMad ? 'pokemon.latitude' : 'lat',
730+
lonColumn: isMad ? 'pokemon.longitude' : 'lon',
731+
idColumn: isMad ? 'pokemon.encounter_id' : 'id',
732+
bounds: {
733+
minLat: args.minLat,
734+
maxLat: args.maxLat,
735+
minLon: args.minLon,
736+
maxLon: args.maxLon,
737+
},
738+
})
686739
const filters = mem
687740
? Object.values(filterMap).flatMap((filter) => filter.buildApiFilter())
688741
: []
689742
if ((perms.iv || perms.pvp) && mem)
690743
filters.push(...globalFilter.buildApiFilter())
691744

692-
const results = await this.evalQuery(
745+
let results = await this.evalQuery(
693746
mem ? `${mem}/api/pokemon/v2/scan` : null,
694747
mem
695748
? JSON.stringify({
@@ -709,6 +762,22 @@ class Pokemon extends Model {
709762
secret,
710763
httpAuth,
711764
)
765+
766+
if (mem && manualId !== null) {
767+
const loaded = new Set(results.map((pkmn) => `${pkmn.id}`))
768+
if (!loaded.has(`${manualId}`)) {
769+
const manualResult = await this.evalQuery(
770+
`${mem}/api/pokemon/id/${manualId}`,
771+
null,
772+
'GET',
773+
secret,
774+
httpAuth,
775+
).catch(() => null)
776+
if (manualResult) {
777+
results = [...results, manualResult]
778+
}
779+
}
780+
}
712781
const filtered = results.filter(
713782
(item) =>
714783
!mem ||

0 commit comments

Comments
 (0)