Skip to content

feat(webhooks): support the PoracleNG v2 API alongside v1 - #4

Closed
Fabio1988 wants to merge 3 commits into
mainfrom
feat/poracle-v2-api
Closed

Fabio1988 wants to merge 3 commits into
mainfrom
feat/poracle-v2-api

Conversation

@Fabio1988

@Fabio1988 Fabio1988 commented Oct 29, 2026 •

Copy link
Copy Markdown
Owner

Summary

PoracleNG's v1 tracking, humans and profiles routes are frozen and deprecated. New behaviour only ships on /api/v2: the separate incident type, [tracking] max_distance enforcement (v1 fix pending in jfberry/PoracleNG#343), and saved-location updates. This PR makes ReactMap use v2 when the Poracle server offers it, and keeps v1 for PoracleJS and older PoracleNG.

The v1/v2 translation happens entirely in the server's Poracle service; v2 results are converted back into the v1 row shape the UI already uses.

It also fixes edits losing settings ReactMap has no input for, on both v1 and v2 (see below).

How it works

  • New webhook option apiVersion (auto by default, or v1 / v2). auto fetches the public /openapi.json once at init and switches to v2 only if every v2 route ReactMap uses is listed. PoracleJS has no spec, so it stays on v1 quietly, without an error log or payload dump. A cached detection result never overrides an explicitly configured version.
  • server/src/services/poracleV2.js maps rules in both directions:
    • v1 sentinels (9000, -1, 4096, 9000000, …) ⇄ v2 omitted/null
    • int enums ⇄ string enums (team, gender, rsvp_changes)
    • packed clean bitmask ⇄ clean / edit / summary. edit is dropped for types v2 rejects it on; summary is kept for quest only.
    • raid pokemon_id / level derivation (boss, by-level, everything)
    • only fields v2 knows are sent (v2 returns 422 for unknown fields such as uid, description, allForms)
  • Pokestop events (gold-stop, kecleon, showcase) stay in the invasion tab. On v2 they are written to and read from the incident type, which v2 keeps separate from invasion. Incident rules have their own uid sequence, so ReactMap shows them with negative uids; edits and deletes are routed to incident by the sign.
  • v2 edits replace the rule by uid (PUT …/tracking/{type}/{uid}), so the rule keeps its id. New rules are POSTed.
  • Humans and profiles use the v2 action endpoints (enable/disable, profile, location, areas, profiles CRUD and copy). Active hours become strict integers on write and padded strings on read. Profile update still writes only active_hours, as v1 did.
  • v2 requests carry no body unless there is one. Bulk DELETE accepts ?uid= or a body, not both.

Edits no longer reset hidden settings (v1 and v2)

Editing a tracked rule sent back only the fields in ReactMap's GraphQL schema, and Poracle replaces a rule wholesale, so anything set from a bot command or PoracleWeb was reset:

  • gym battle_changes: the toggle existed, but the stored value never reached it
  • the edit and summary bits of clean (GraphQL's Boolean turned 3 into true, saved back as 1)
  • pokemon/raid costume, raid evolution, pokemon pvp_ranking_evolution
  • override_areas / override_location_label

Fixes:

  • battle_changes is now in the GraphQL schema, and clean resolves to the clean bit only.
  • server/src/services/poracleRules.js: before an edit is sent, the hidden settings are copied over from the stored rule. A setting the edit made invalid is dropped: an area override once a distance is set, a location override once the distance is 0, a PVP evolution once the rule is no longer PVP or changes league.
  • PVP pokemon edits now keep their uid, so they update the rule instead of adding a second one.

Test plan

  • server/test/poracleV2.test.js: mapping for every category, plus a stub HTTP server covering detection (v2 spec / no spec / partial spec / forced), the invasion/incident split and PUT-by-uid edits, bulk delete by uid sign without a body, the profile PATCH body, cache-vs-config precedence, the clean-bit merge, hidden-setting merging, and a v1 edit carrying the stored settings
  • Full server suite, run directly with node --test (local Node 22.23.3 is one patch below the engine pin, so yarn test refuses to start): 174/174 pass
  • Bodies built from each category's UI defaults, and merged edits with costume / evolution / overrides, validated with ajv against the v2 rule schemas in PoracleNG's OpenAPI spec (additionalProperties: false, enums, minimums): all valid
  • Manual check: edit a rule that has costume, an override, battle_changes or the edit bit set from a bot command, and confirm it survives
  • Manual check against a live PoracleNG: list, add, edit and delete per category, quick gym, profiles (add, schedule, copy, delete), areas, location, start/stop
  • Manual check against PoracleJS: still detected as v1

Known limitations

  • ReactMap still can't set costume, overrides, PVP evolution or the edit/summary bits; it only keeps them on edit.
  • The event names gold-stop, kecleon and showcase are mapped to display_type 7, 8 and 9 in code, matching PoracleNG's util.json.

🤖 Generated with Claude Code

Fabio1988 and others added 3 commits October 29, 2026 17:33
PoracleNG's v1 tracking/humans/profiles API is frozen and deprecated; new
features (incident tracking, max_distance enforcement, saved locations) only
ship on /api/v2. Talk v2 when the server offers it and keep v1 for PoracleJS
and older PoracleNG.

- New webhook option `apiVersion`: 'auto' (default), 'v1' or 'v2'. 'auto'
  checks the public /openapi.json for every v2 route the service uses.
- server/src/services/poracleV2.js translates rules both ways: v1 sentinels
  <-> v2 null/omitted, int enums <-> string enums, clean bitmask <->
  clean/edit/summary. The frontend and GraphQL schema keep the v1 shape.
- Pokestop events (gold-stop, kecleon, showcase) stay under invasion in the
  UI but are written to and read from v2's incident type.
- v2 requests are sent without an empty body (bulk DELETE is strict about it).
- A cached detection result never overrides a configured apiVersion.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Editing a tracked rule sent back only the fields the GraphQL schema
exposes, and Poracle replaces a rule wholesale, so settings made
elsewhere were reset: gym battle_changes, the edit and summary clean
bits, pokemon/raid costume, raid evolution, PVP mega evolution, and
override_areas / override_location_label.

- expose battle_changes to the client, and show `clean` as the clean
  bit only
- before an edit is sent, copy the hidden settings over from the stored
  rule (v1 and v2), dropping ones the edit made invalid
- v2: edits replace the rule by uid (PUT) instead of POSTing a new one,
  costume / pvp evolution / overrides map both ways, and incident rules
  get negative uids so they no longer collide with invasion uids
- PVP pokemon edits keep their uid

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ReactMap has a battle_changes toggle and the field is now in the GraphQL
schema, so every edit carries it; the fallback never applied.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Fabio1988 Fabio1988 closed this Oct 29, 2026
@Fabio1988

Copy link
Copy Markdown
Owner Author

Superseded by WatWowMap#1273.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant