Upgrading & Release Notes¶
This page covers what changes between PoracleNG releases and what to check when you upgrade. For moving from PoracleJS, see the Migration Guide.
| Branch | Version | Go (source builds) | Docker tag |
|---|---|---|---|
main |
5.2.x (current: 5.2.1) | 1.25+ | ghcr.io/jfberry/poracleng:main / :latest |
develop |
5.3.0-dev | 1.27+ | ghcr.io/jfberry/poracleng:develop |
!version shows the version you are running, with the branch, commit and build date.
Before Every Upgrade¶
Back up your database
Pending migrations run automatically when the processor starts, and there is no downgrade command. An older build will refuse to start against a schema migrated by a newer one, and some migrations rewrite data. Take a backup first:
For Docker, see Docker → Updating.
Then:
- Read the notes below for every version between yours and the target.
- Update:
git pull && make build, then restart. Or for Docker:docker compose pull && docker compose up -d. - Check the startup log for
Database migrated to version N(orDatabase schema is up to date) and for anyWARNlines. - Run
!poracle-admin warnings startupto list warnings raised during startup.
5.3.0 (develop)¶
PoracleNG 5.3+
Everything in this section is only on the develop branch / :develop image so far.
Breaking / Action Required¶
Go 1.27¶
Building from source now needs Go 1.27. The Docker image is unaffected.
Migration 000009: profile 0 → profile 1¶
Earlier versions created new humans on profile 0, through !poracle, Discord role reconciliation, !channel add, !webhook add and Telegram channel registration. Profile 0 had no profiles row, but the default profile is 1. Bot commands still worked, because they saved to the current profile (0). Anything that addressed profile 1 directly, such as PoracleWeb, saved rules that never matched. A user who switched to profile 2 could never switch back to their profile-0 rules.
New humans now start on profile 1, and migration 000009 repairs existing data:
- Humans currently on profile 0: their live area/location is copied onto profile 1 (which is created if missing), their profile-0 rules are moved to profile 1, and they are switched to profile 1.
- Humans who switched away from profile 0 and whose profile 1 has no rules: the profile-0 rules move to profile 1, restoring their lost default profile.
- Humans who switched away and had since rebuilt profile 1: the profile-0 rules are deleted as abandoned. They hadn't fired since the switch and the user couldn't see them.
- Profile-0 rules identical to an existing profile-1 rule are dropped as duplicates.
- Humans with a genuine
profilesrow for profile 0 are left untouched.
Irreversible
The down migration is a no-op, and no record is kept of which rows were on profile 0. The only way back is your backup.
Delivery: oldest alert dropped on a full lane¶
When a destination's lane ([tuning] delivery_queue_size) is full, the oldest queued alert is now dropped to make room. In 5.2, the producer waited instead, and one stuck destination could stall every render worker. Watch for delivery: lane full … shedding oldest queued messages and the [Status] delivery shedding messages warning, and alert on poracle_delivery_lane_shed_total. See Rate Limits → Delivery Lanes.
Rate-limit bans fire once¶
An auto-disable ban now fires once per 24-hour violation window, instead of repeating the farewell, shame post and admin notice every timing_period while a backlog drains. Re-enabling a destination with !start or !enable clears its breach history, so a repeat offender is banned again. See Rate Limits.
Behind a reverse proxy: set trusted_proxies¶
X-Forwarded-For / X-Real-IP are now only believed from addresses listed in the new [processor] trusted_proxies (IPs or CIDRs; empty by default). Before, any client could set those headers and get past ip_whitelist / ip_blacklist. If PoracleNG sits behind nginx, Traefik or a Docker network and you use the IP lists, add the proxy, e.g. trusted_proxies = ["172.16.0.0/12"], or every request is seen as coming from the proxy. The IP lists now also accept CIDR ranges, and an invalid entry in any of the three lists stops startup. See [processor].
/debug/pprof is off by default¶
Go profiling is no longer served unauthenticated. It only exists with [processor] enable_pprof = true, and then needs the X-Poracle-Secret header like /api. Startup also warns when api_secret is blank and the API listens on a non-loopback host (including Docker's 0.0.0.0).
[discord] / [telegram] enabled = false stops alerts¶
enabled = false now stops that platform's alerts (Discord webhooks count as Discord), not just its commands. config.example.toml ships [telegram] enabled = false: if you added a Telegram token and left that line, Telegram alerts stop after upgrading. Set enabled = true or delete the line. Startup warns when a platform has a token but is disabled.
!restore replaces all tracking¶
!restore now clears every tracking type on the target's current profile and refills it from the backup in one transaction, so types missing from the backup end up empty. Before, it only replaced the types present in the file. Table and column names in the file are validated first. See Backup & Restore.
API v2 response shapes and stable rule uids¶
API v2 clients need updating: humans and profiles now use real booleans and arrays instead of the v1 0/1 flags and JSON-encoded strings, language is "" when unset, location bodies and check-location use latitude/longitude instead of lat/lon, and the snapshot's summaries[] loses id. PUT …/tracking/{type}/{uid} now keeps the rule's uid, and editing a rule through a bot command, v1 or v2 POST keeps its uid too, so id:N references, rule mutes and alert buttons survive edits. v1 is unchanged. See API v2 and v2 tracking.
Other behaviour changes¶
- Commands are stricter. Arguments that used to be accepted and ignored are now reported:
!track … shiny, an unknownmove:on!raid/!maxbattle(it used to mean "any move"), andgen/type names on!raid.!maxbattlewith a gen or type but no pokemon is refused. An unrecognised word on!invasion remove/!incident removeis rejected; it used to delete every invasion rule. !questwith several rewards now creates a rule for each reward named, not just the first.usertarget override must be numeric (user:123…,user-100…). Words that merely start with "user" are no longer taken as an override.- Admins bypass
[discord.command_security]on text commands andPOST /api/commandtoo, not just slash commands. - Delegated admins work: Discord category targets (and a thread's parent channel),
[[telegram.delegated_admins]], and Telegram community admins managing their groups and running/userlist. See Discord and Telegram. !enable,!disable,!unregisterlist unregistered IDs as "Not registered" instead of reporting success.- Rarity:
rarity:6(Unseen) now matches species with no sightings in the window, so rules with a minimum rarity (e.g.rarity:rare) also fire for unseen species. - Templates: a user's language-specific default template is now chosen over the language-less default.
previousControlTeamEmojishows the previous controller's team (it showed the old team), and maxbattle{{id}}is the boss pokemon ID instead of the station ID. See DTS fields. !weatherremoved. It always replied "unavailable".!info weatheris unaffected.- Slash commands re-register on the next start, because their definitions changed (
/fortlosescleanand gains Station/Everything;/profile copytoaccepts the autocompleted number). config.example.tomlcleaned up: keys the code never read are gone, andfilter_max_ranknow shows the real default100(was10). If you copied the old example, nothing changes, but you can deleteenvironment,worker_status,worker_activity,sprite_*,scale,encounter_cache_ttl,batch_size,flush_interval_millisand the old alerter tuning keys. Leaving outthread_keep_alive_interval_hoursorremoval_safety_max_percentmeans0(off), not the example's value; the Config UI no longer drops them when saved.
New¶
- Pokemon
edit.!track … editedits the original alert in place when the pokemon changes, instead of sending a threaded follow-up. New[tracking]keys:pokemon_edit(defaulttrue) andpokemon_edit_window_mins(default5,0= no limit). Slash/track,/raid,/eggand/luregain aneditoption. [tracking] default_edit. A list of alert types that behave as if every rule hadedit. Supported types arepokemon,raid,egg,lureandincident.- PVP
level_capsmismatch warning. If Golbat sends ranks for a level cap that isn't in[pvp] level_caps, aPVP configuration mismatchwarning is logged once per cap. Those ranks were always ignored; now you are told. - Unsubscribe button now works on pokemon and fort-update alerts.
- PoracleJS DTS compatibility improvements: custom maps (
{{map}}/{{map2}}), evolution fields, extra string helpers, andGET /api/dts/custommapsfor the DTS editor. - API: v2 tracking accepts
ping,DELETE /api/v2/humans/{id}/locationclears a location, v2 clamps distances to[tracking] max_distance, and there is a newGET /api/geocode/reverse. !poracle-admin configoutput is now in code blocks, which fixes mangledsnake_casekeys on Telegram.!poracle-test nest riverside: bundled nest test data. Withlocation: "current"the nest (and its polygon) moves to the tester.!scriptnow exports!maxbattleand!fortrules.POST /api/commandadds the command prefix to lines that lack it, sotrack pikachuworks as well as!track pikachu.!pa configsection names and search terms ignore case and treat_and spaces alike (!pa config alert_limits).!nest everything gen1/everything fireapply the gen/type filter instead of ignoring it.!info <pokemon> form:also accepts the translated prefix (e.g. Frenchforme:).
Fixes worth knowing¶
- PVP rules stored with
pvp_ranking_worst = 0now match (0is treated as "no limit"). - Re-running a tracking command with only a different
pingupdates the rule instead of adding a copy. - Weather-change alerts are no longer dropped when Golbat re-sends quickly. A species change that keeps the same CP (e.g. a Ditto reveal) now produces a change alert.
{{latitude}}/{{longitude}}now render in fort-update templates.- The v2
?profile=on location/areas no longer overwrites the active profile's live location. !channel add area:<name_with_underscores>andname:values with underscores are no longer silently dropped.!lure remove id:N(and so/untrack lure) and!maxbattle remove level:Nnow remove rules;!unmute areais case-insensitive; per-type mute aliases (!raid mute gym X) work.rarity:very-rare/ultra-rareparse.- Trace-level logging no longer crashes the processor;
{{#pokemon id}}without a form no longer panics; help and greeting templates render in the user's language and can't crash the bot. {{ex}},oldTeamEmojiandshowcaseFocusEmojiare populated.- Alerts that fall back say why: "Template not found", "Template render error" or "Template produced invalid JSON".
!pa maintenancereplies now say paused alerts are dropped (they never were queued).examples/broadcast.jsonis valid JSON, and the!broadcasthelp matches the command.monitoring/prometheus.yml.exampleno longer scrapes the removed alerter on port 3031.
5.2.x (main)¶
Breaking / Action Required¶
Logging level names¶
[logging] level now accepts trace, debug, info and warn (default info). The PoracleJS names are aliases: verbose means info and silly means trace. In 5.1 and earlier, neither alias was recognised and both fell back to info. A config left on silly therefore goes from info-level output to the most verbose level after upgrading. Set level = "info" unless you want that. Legacy log_level / console_log_level keys are folded into level.
disable_pokestop is a no-op¶
[general] disable_pokestop is still accepted but does nothing. Use disable_lure, disable_invasion, disable_quest, and the new disable_showcase. See Scanner Setup.
delivery_queue_size is now per destination¶
Delivery moved to per-destination lanes. [tuning] delivery_queue_size (default 200) is now the buffer for each active destination, not one shared queue, so memory under a backlog grows with the number of destinations. If you raised it a lot for the old shared queue, bring it back toward the default. Idle lanes are removed after 60 seconds. New poracle_delivery_lane_* metrics are listed on the Monitoring page.
Migrations 000006–000008¶
These add a costume column to monsters and raid, and drop the legacy invasion_tracking / lure_tracking unique keys. They are applied automatically.
New¶
- Showcases. Pokestop contests are now alerts, driven by the
pokestopwebhook, with their ownshowcaseDTS template anddisable_showcase. - Costume tracking.
costume:<name|id>works on!trackand!raid. - Quest pokecoin rewards (
pokecoins). - OpenAPI and
/api/v2.GET /openapi.jsonand interactive docs at/docs. v1 tracking/humans/profiles endpoints are frozen and deprecated. Error bodies are now RFC 9457problem+json. Includes a v2 mutes API. - Geocoding: GeoNames
intersection_usersfor{{intersection}}, and shared circuit breakers on external services. - Delivery lanes, quest wildcard fixes, lure multi-type fixes, and channel auto-create no longer moves a same-named channel out of another category.
5.1.0¶
- Version reporting.
!versionshows the commit, branch and build date. - PVP mega evolutions.
mega,mega:xandmega:ykeywords on PVP rules (migration 000005 addspvp_ranking_evolution).[pvp] include_mega_evolutionchanged meaning: it is now only the default for rules without amegakeyword (false= base forms only;true= include mega ranks). A per-rule keyword always overrides it. - Per-rule location/area overrides, quest summaries, Photon geocoding, and the Rampardos static map provider.
PoracleJS migration script fixes¶
If you converted a PoracleJS config before 5.1.0, check two things the old scripts/migrate-from-poracle.js got wrong:
[general.dts_dictionary]— custom keys were snake-cased (scannerUrl→scanner_url), so templates using{{scannerUrl}}render empty. Rename the keys back to exactly what your templates use.[processor] host— PoracleJS'sserver.hostwas dropped. Set it again if you bound the API to a specific address.