Skip to content

Commit

Permalink
Merge pull request #891 from KartulUdus/develop
Browse files Browse the repository at this point in the history
Sync develop to master
  • Loading branch information
jfberry authored Jan 9, 2024
2 parents 8f1786c + 5332022 commit 5552dea
Show file tree
Hide file tree
Showing 17 changed files with 154 additions and 75 deletions.
4 changes: 4 additions & 0 deletions locale/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"Attack":"Angriff",
"Autumn":"Herbst",
"Available forms": "verfügbare Formen",
"Average": "Average",
"Black":"Schwarz",
"Battle a Team Leader 2 times":"Kämpfe 2 mal gegen einen Team Rocket Leader",
"Battle Another Trainer 2 times":"Kämpfe 2 mal gegen einen anderen Trainer",
Expand Down Expand Up @@ -323,6 +324,7 @@
"Land":"Land",
"Land 3 throws":"Lande 3 Würfe",
"language":"Sprache",
"Large": "Large",
"Legendary":"Legendär",
"level":"Level",
"Level 1 Shadow":"Crypto Level 1",
Expand Down Expand Up @@ -521,6 +523,7 @@
"size":"Größe",
"Sky":"Zenit",
"slot changes":"Platzänderung",
"Small": "Small",
"snow":"Schnee",
"Snowy":"Schneeform",
"Something went wrong with your request":"Bei deiner Anfrage ist ein Fehler aufgetreten",
Expand All @@ -546,6 +549,7 @@
"Sun Stone":"Sonnenstein",
"Sunny":"Sonnenform",
"sunny":"Sonnig",
"Super": "Super",
"Super Effective Against":"sehr effektiv gegen",
"Super Potion":"Supertrank",
"Take 3 Snapshots":"Mache 3 Fotos",
Expand Down
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "poracle",
"version": "4.6.2",
"version": "4.7.0",
"description": "Webhook processing and personalised discord|telegram alarms",
"keywords": [
"poracle",
Expand Down Expand Up @@ -41,13 +41,14 @@
"deep-object-diff": "^1.1.9",
"discord.js": "^13.16.0",
"fast-json-stable-stringify": "^2.1.0",
"fastify": "^4.23.0",
"fastify": "^4.25.2",
"flat-cache": "^3.0.4",
"form-data": "^4.0.0",
"geo-tz": "^7.0.7",
"handlebars": "^4.7.7",
"hastebin-gen": "^2.0.5",
"import-fresh": "^3.3.0",
"json5": "^2.2.3",
"knex": "^2.0.0",
"moment": "^2.29.4",
"moment-precise-range-plugin": "^1.3.0",
Expand All @@ -60,6 +61,7 @@
"nodes2ts": "^3.0.0",
"ohbem": "^1.5.1",
"point-in-polygon": "^1.1.0",
"rbush": "^3.0.1",
"readline-sync": "^1.4.10",
"s2-geometry": "^1.2.10",
"strip-json-comments": "^3.1.1",
Expand Down
13 changes: 9 additions & 4 deletions src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,7 @@ async function processOne(hook) {
fastify.controllerLog.debug(`${hook.message.encounter_id}: Wild encounter was received but set to be ignored in config`)
break
}
if (!hook.message.poracleTest) {
if (!hook.message.poracleTest && !config.tuning?.disablePokemonCache) {
fastify.webhooks.info(`pokemon ${JSON.stringify(hook.message)}`)
const verifiedSpawnTime = (hook.message.verified || hook.message.disappear_time_verified)
const cacheKey = `${hook.message.encounter_id}${verifiedSpawnTime ? 'T' : 'F'}${hook.message.cp}`
Expand Down Expand Up @@ -902,8 +902,12 @@ async function run() {
setTimeout(processPogoEvents, 30000)
setTimeout(processPossibleShiny, 30000)

let watchGeofence = Array.isArray(config.geofence.path) ? config.geofence.path : [config.geofence.path]
watchGeofence = watchGeofence.map((x) => path.join(__dirname, `../${x}`))
let watchGeofence = Array.isArray(config.geofence.path)
? config.geofence.path
: [config.geofence.path]
watchGeofence = watchGeofence.map((x) => (x.startsWith('http')
? path.join(__dirname, '../.cache', `${x.replace(/\//g, '__')}.json`)
: path.join(__dirname, `../${x}`)))

chokidar.watch(watchGeofence, {
awaitWriteFinish: true,
Expand All @@ -919,7 +923,8 @@ async function run() {

// This splice mechanism replaces array in place (relies on no caching)
const newGeofence = require('./lib/geofenceLoader').readAllGeofenceFiles(config)
geofence.splice(0, geofence.length, ...newGeofence)
geofence.rbush = newGeofence.rbush
geofence.geofence = newGeofence.geofence
} catch (err) {
log.error('Error reloading dts', err)
}
Expand Down
25 changes: 22 additions & 3 deletions src/controllers/controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -390,9 +390,20 @@ class Controller extends EventEmitter {
}

pointInArea(point) {
if (!this.geofence.length) return []
if (!this.geofence.geofence.length) return []

const result = this.geofence.rbush.search({
minX: point[0],
minY: point[1],
maxX: point[0],
maxY: point[1],
})

const matchAreas = []
for (const areaObj of this.geofence) {

for (const potential of result) {
const areaObj = potential.fence

if (areaObj.path) {
if (inside(point, areaObj.path)) {
matchAreas.push({
Expand All @@ -416,7 +427,15 @@ class Controller extends EventEmitter {
}
}
}
return matchAreas

const dedupedList = []

for (const match of matchAreas) {
if (!dedupedList.some((x) => x.name === match.name)) {
dedupedList.push(match)
}
}
return dedupedList
}

// database methods below
Expand Down
29 changes: 11 additions & 18 deletions src/controllers/fortupdate.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const moment = require('moment-timezone')
const Controller = require('./controller')

/**
* Controller for processing nest webhooks
* Controller for processing fort update webhooks
*/
class FortUpdate extends Controller {
async fortUpdateWhoCares(obj) {
Expand Down Expand Up @@ -47,7 +47,7 @@ class FortUpdate extends Controller {
// group by humans.id, humans.name, humans.type, humans.language, humans.latitude, humans.longitude, invasion.template, invasion.distance, invasion.clean, invasion.ping
} else {
query = query.concat(`
and ((nests.distance = 0 and (${areastring})) or nests.distance > 0)
and ((forts.distance = 0 and (${areastring})) or forts.distance > 0)
`)
// group by humans.id, humans.name, humans.type, humans.language, humans.latitude, humans.longitude, invasion.template, invasion.distance, invasion.clean, invasion.ping
}
Expand Down Expand Up @@ -96,23 +96,17 @@ class FortUpdate extends Controller {
}
data.name = this.escapeJsonString(data.name)

const nestExpiration = data.reset_time + (7 * 24 * 60 * 60)
data.tth = moment.preciseDiff(Date.now(), nestExpiration * 1000, true)
data.disappearDate = moment(nestExpiration * 1000).tz(geoTz.find(data.latitude, data.longitude)[0].toString()).format(this.config.locale.date)
const expiration = data.reset_time + (7 * 24 * 60 * 60)
data.tth = moment.preciseDiff(Date.now(), expiration * 1000, true)
data.disappearDate = moment(expiration * 1000).tz(geoTz.find(data.latitude, data.longitude)[0].toString()).format(this.config.locale.date)
data.resetDate = moment(data.reset_time * 1000).tz(geoTz.find(data.latitude, data.longitude)[0].toString()).format(this.config.locale.date)
data.disappearTime = moment(nestExpiration * 1000).tz(geoTz.find(data.latitude, data.longitude)[0].toString()).format(this.config.locale.time)
data.disappearTime = moment(expiration * 1000).tz(geoTz.find(data.latitude, data.longitude)[0].toString()).format(this.config.locale.time)
data.resetTime = moment(data.reset_time * 1000).tz(geoTz.find(data.latitude, data.longitude)[0].toString()).format(this.config.locale.time)

data.applemap = data.appleMapUrl // deprecated
data.mapurl = data.googleMapUrl // deprecated
data.distime = data.disappearTime // deprecated

// Stop handling if it already disappeared or is about to go away
// if (data.tth.firstDateWasLater || ((data.tth.days * 24 * 3600) + (data.tth.hours * 3600) + (data.tth.minutes * 60) + data.tth.seconds) < minTth) {
// this.log.debug(`${data.pokestop_id} Nest already disappeared or is about to go away in: ${data.tth.days}d ${data.tth.hours}:${data.tth.minutes}:${data.tth.seconds}`)
// return []
// }

data.matchedAreas = this.pointInArea([data.latitude, data.longitude])
data.matched = data.matchedAreas.map((x) => x.name.toLowerCase())

Expand Down Expand Up @@ -212,14 +206,12 @@ class FortUpdate extends Controller {

if (discordCacheBad) {
whoCares.forEach((cares) => {
this.log.verbose(`${logReference}: Not creating nest alert (Rate limit) for ${cares.type} ${cares.id} ${cares.name} ${cares.language} ${cares.template}`)
this.log.verbose(`${logReference}: Not creating fort update alert (Rate limit) for ${cares.type} ${cares.id} ${cares.name} ${cares.language} ${cares.template}`)
})

return []
}

data.shinyPossible = this.shinyPossible.isShinyPossible(data.pokemonId, data.formId)

data.stickerUrl = data.imgUrl

const geoResult = await this.getAddress({ lat: data.latitude, lon: data.longitude })
Expand Down Expand Up @@ -260,16 +252,17 @@ class FortUpdate extends Controller {
let [platform] = cares.type.split(':')
if (platform === 'webhook') platform = 'discord'

const now = new Date()
const time = moment.tz(now, this.config.locale.time, geoTz.find(data.latitude, data.longitude)[0].toString())
const view = {
...geoResult,
...data,
time: data.distime,
tthd: data.tth.days,
tthh: data.tth.hours,
tthm: data.tth.minutes,
tths: data.tth.seconds,
now: new Date(),
nowISO: new Date().toISOString(),
time: time.format(this.config.locale.time),
nowISO: now.toISOString(),
areas: data.matchedAreas.filter((area) => area.displayInMatches).map((area) => area.name).join(', '),
}

Expand Down
6 changes: 4 additions & 2 deletions src/controllers/query.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,12 @@ class Query {
}

pointInArea(point) {
if (!this.geofence.length) return []
const { geofence } = this.geofence

if (!geofence.length) return []
const matchAreas = []

for (const areaObj of this.geofence) {
for (const areaObj of geofence) {
if (areaObj.path && inside(point, areaObj.path)) matchAreas.push(areaObj.name.toLowerCase())
if (areaObj.multipath) {
for (const p of areaObj.multipath) {
Expand Down
2 changes: 1 addition & 1 deletion src/lib/configFetcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ module.exports = {
if (performChecks) {
configChecker.checkConfig(config)
configChecker.checkDts(dts, config)
configChecker.checkGeofence(geofence)
configChecker.checkGeofence(geofence.geofence)
}

moment.locale(config.locale.timeformat)
Expand Down
2 changes: 1 addition & 1 deletion src/lib/discord/commando/commands/channel.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ exports.run = async (client, msg, [args]) => {
[,, areaName] = areaName.match(client.re.areaRe)
areaName = areaName.toLowerCase()
}
const confAreas = client.geofence.map((area) => area.name.toLowerCase()).sort()
const confAreas = client.geofence.geofence.map((area) => area.name.toLowerCase()).sort()
const isValidArea = confAreas.filter((x) => areaName === x)
if (!isValidArea.length) {
areaName = ''
Expand Down
50 changes: 49 additions & 1 deletion src/lib/geofenceLoader.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const stripJsonComments = require('strip-json-comments')
const fs = require('fs')
const path = require('path')
const RBush = require('rbush')
const { log } = require('./logger')

function getGeofenceFromGEOjson(config, rawdata) {
Expand Down Expand Up @@ -74,6 +75,29 @@ function readGeofenceFile(config, filename) {
return geofence
}

function getBoundingBox(fencePath) {
let minX = Number.MAX_VALUE; let minY = Number.MAX_VALUE; let maxX = Number.MIN_VALUE; let maxY = Number.MIN_VALUE

for (const point of fencePath) {
if (point[0] < minX) {
[minX] = point
}
if (point[0] > maxX) {
[maxX] = point
}
if (point[1] < minY) {
[, minY] = point
}
if (point[1] > maxY) {
[, maxY] = point
}
}

return {
minX, minY, maxX, maxY,
}
}

function readAllGeofenceFiles(config) {
const fencePaths = Array.isArray(config.geofence.path) ? config.geofence.path : [config.geofence.path]
const geofence = fencePaths.flatMap((fencePath) => readGeofenceFile(
Expand All @@ -82,7 +106,31 @@ function readAllGeofenceFiles(config) {
? path.resolve(__dirname, '../../.cache', `${fencePath.replace(/\//g, '__')}.json`)
: path.join(__dirname, `../../${fencePath}`),
))
return geofence

const tree = new RBush()

for (const areaObj of geofence) {
if (areaObj.path && areaObj.path.length > 0) {
tree.insert({
...getBoundingBox(areaObj.path),
fence: areaObj,
})
} else if (areaObj.multipath) {
for (const p of areaObj.multipath) {
if (p.length > 0) {
tree.insert({
...getBoundingBox(p),
fence: areaObj,
})
}
}
}
}

return {
rbush: tree,
geofence,
}
}

module.exports = { readAllGeofenceFiles }
12 changes: 6 additions & 6 deletions src/lib/poracleMessage/commands/area.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ exports.run = async (client, msg, args, options) => {
return msg.reply(translator.translate('You do not have permission to execute this command'))
}

let selectableGeofence = client.geofence
let selectableGeofence = client.geofence.geofence
// Note for Poracle admins we don't remove the userSelectable items
// But we do apply the filtering later based on the user/channel that is the target (targetIsAdmin used instead)
if (!msg.isFromAdmin) selectableGeofence = selectableGeofence.filter((area) => area.userSelectable ?? true)
Expand Down Expand Up @@ -102,7 +102,7 @@ exports.run = async (client, msg, args, options) => {
if (areasNotAlreadyInList.length) {
await msg.reply(`${translator.translate('Added areas:')} ${areasNotAlreadyInList.map((x) => x.name).join(', ')}`)
}
await msg.reply(trackedCommand.currentAreaText(translator, client.geofence, uniqueNewAreas))
await msg.reply(trackedCommand.currentAreaText(translator, client.geofence.geofence, uniqueNewAreas))

await client.query.updateQuery('profiles', { area: JSON.stringify(uniqueNewAreas) }, {
id: target.id,
Expand Down Expand Up @@ -136,7 +136,7 @@ exports.run = async (client, msg, args, options) => {
if (removeAreasPresent.length) {
await msg.reply(`${translator.translate('Removed areas:')} ${removeAreasPresent.map((x) => x.name).join(', ')}`)
}
await msg.reply(trackedCommand.currentAreaText(translator, client.geofence, uniqueNewAreas))
await msg.reply(trackedCommand.currentAreaText(translator, client.geofence.geofence, uniqueNewAreas))

await client.query.updateQuery('profiles', { area: JSON.stringify(uniqueNewAreas) }, { id: target.id, profile_no: currentProfileNo })
break
Expand Down Expand Up @@ -176,7 +176,7 @@ exports.run = async (client, msg, args, options) => {
case 'overview': {
if (client.config.geocoding.staticProvider.toLowerCase() === 'tileservercache') {
const staticMap = await geofenceTileGenerator.generateGeofenceOverviewTile(
client.geofence,
client.geofence.geofence,
client.query.tileserverPregen,
args.length >= 2 ? args : JSON.parse(human.area),
)
Expand Down Expand Up @@ -210,7 +210,7 @@ exports.run = async (client, msg, args, options) => {
}
} else {
staticMap = await geofenceTileGenerator.generateGeofenceTile(
client.geofence,
client.geofence.geofence,
client.query.tileserverPregen,
area,
)
Expand All @@ -228,7 +228,7 @@ exports.run = async (client, msg, args, options) => {
break
}
default: {
await msg.reply(trackedCommand.currentAreaText(translator, client.geofence, JSON.parse(human.area)))
await msg.reply(trackedCommand.currentAreaText(translator, client.geofence.geofence, JSON.parse(human.area)))

await msg.reply(
translator.translateFormat('Valid commands are `{0}area list`, `{0}area add <areaname>`, `{0}area remove <areaname>`', util.prefix),
Expand Down
4 changes: 2 additions & 2 deletions src/lib/poracleMessage/commands/tracked.js
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ exports.run = async (client, msg, args, options) => {

const maplink = `https://maps.google.com/maps?q=${human.latitude},${human.longitude}`
if (args.includes('area')) {
return msg.reply(currentAreaText(translator, client.geofence, JSON.parse(human.area)))
return msg.reply(currentAreaText(translator, client.geofence.geofence, JSON.parse(human.area)))
}

let message = ''
Expand All @@ -267,7 +267,7 @@ exports.run = async (client, msg, args, options) => {
}
await msg.reply(`${adminExplanation}${translator.translate('Your alerts are currently')} **${human.enabled ? `${translator.translate('enabled')}` : `${translator.translate('disabled')}`}**${restartExplanation}${locationText}`, { style: 'markdown' })

message = message.concat('\n\n', currentAreaText(translator, client.geofence, JSON.parse(human.area)))
message = message.concat('\n\n', currentAreaText(translator, client.geofence.geofence, JSON.parse(human.area)))

if (profile) {
message = message.concat('\n\n', `${translator.translate('Your profile is currently set to:')} ${profile.name}`)
Expand Down
Loading

0 comments on commit 5552dea

Please sign in to comment.