Skip to content

Add maxbattle (max_battle) webhook type#14

Closed
jfberry wants to merge 12 commits intomainfrom
maxbattle
Closed

Add maxbattle (max_battle) webhook type#14
jfberry wants to merge 12 commits intomainfrom
maxbattle

Conversation

@jfberry
Copy link
Copy Markdown
Owner

@jfberry jfberry commented Mar 16, 2026

Summary

  • Full maxbattle webhook support across processor and alerter
  • Based on PoracleJS PR #929 adapted for PoracleNG's split architecture
  • Processor handles matching/dedup/enrichment, alerter handles rendering/delivery

Processor (Go)

  • Webhook struct, receiver routing for max_battle type from Golbat
  • DB migration for maxbattle table (pokemon_id, gmax, level, form, move, evolution, distance, station_id)
  • Matcher with filters: pokemon/level, gmax, form, evolution, move, station_id, specificstation blocked check
  • Duplicate cache keyed on station_id + battle_end + pokemon_id
  • Enrichment: disappear time, TTH, weather, sun times

Alerter (Node.js)

  • Controller with full DTS enrichment (moves, types, weakness calcs, weather boost, icons with bread mode)
  • !maxbattle command: track by pokemon name, level, gmax, move, form, distance, clean, remove
  • Discord + Telegram command wrappers (auto-registered)
  • API tracking CRUD (/api/tracking/maxbattle/:id)
  • Integration: tracked, backup, unregister, profile (delete + copyto), script, poracle-test
  • Reconciliation cleanup (Discord channel delete, Discord/Telegram user removal)
  • apiConfig disabledHooks, apiTracking combined endpoints
  • Default DTS templates (Discord embed + Telegram), tileserver templates (day + night)
  • Test data from real captured webhooks
  • uicons.js bread mode parameter for Dynamax icon variants

Test plan

  • !poracle-test max-battle level1 / level3 / gmax renders correctly
  • !maxbattle level3 adds tracking, !tracked shows it
  • !maxbattle pikachu gmax adds pokemon-specific tracking
  • !maxbattle remove everything clears all maxbattle trackings
  • Live max_battle webhooks from Golbat trigger alerts for matched users
  • API: POST/GET/DELETE /api/tracking/maxbattle/:id works
  • Backup/restore includes maxbattle entries
  • Profile delete/copyto handles maxbattle table

🤖 Generated with Claude Code

@jfberry jfberry force-pushed the maxbattle branch 2 times, most recently from ea713a5 to 89b826b Compare March 16, 2026 21:20
@jfberry jfberry changed the base branch from shared-config to main March 17, 2026 20:45
@jfberry jfberry requested a review from ReuschelCGN March 17, 2026 20:45
@jfberry jfberry force-pushed the maxbattle branch 3 times, most recently from fd529c8 to ff49121 Compare March 18, 2026 13:38
jfberry and others added 11 commits March 19, 2026 13:19
Comprehensive checklist covering processor (webhook receiving, DB, state,
matching, enrichment, wiring), alerter (controller, commands, API CRUD,
reconciliation, backup, profile, DTS templates, tileserver), and config.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- DB migration for maxbattle table (pokemon_id, gmax, level, form, move,
  evolution, distance, station_id, etc.)
- Webhook struct, receiver routing for "max_battle" type
- Matcher with filters: pokemon/level, gmax, form, evolution, move, station
- Duplicate cache keyed on station_id + battle_end + pokemon_id
- Enrichment: disappear time, TTH, weather, sun times
- Handler: dedup, match, enrich, send to alerter
- Wired into state loader, DB loader, and ProcessorService

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New files:
- Controller (handleMatched with full DTS enrichment, pokemon data,
  moves, weather, type weakness, icons, static maps)
- poracleMessage command (!maxbattle with pokemon/level/gmax/move/form
  tracking, remove, everything)
- Discord + Telegram command wrappers
- API tracking CRUD route (/api/tracking/maxbattle/:id)

Integration into existing files:
- app.js: controller instantiation + processOne dispatch
- tracked.js: maxbattleRowText + display in !tracked
- backup.js: include in backup/restore
- unregister.js: cleanup on unregister
- profile.js: cleanup on profile delete + copyto
- script.js: include in script generation
- channelDelete.js: cleanup on Discord channel delete
- discordReconciliation.js: cleanup + commandSecurity
- telegramReconciliation.js: cleanup
- apiConfig.js: disabledHooks list
- apiTracking.js: combined tracking GET endpoints

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- maxbattleLevels data in util.json (level 1-8 names)
- Default DTS templates for Discord + Telegram in fallbacks/dts.json
- Test data (level1, level3, gmax) in fallbacks/testdata.json
- poracle-test.js: add max-battle to valid hooks with timestamp freshening
- Tileserver templates (day + night variants)
- config.example.toml: disable_max_battle option

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Gmax threshold: change > 5 to > 6 (levels 7+ are gmax, matching PR)
- Remove level 6 from maxbattleLevels (PR skips from 5 to 7)
- Add full weakness/resistance calculation to alerter controller
- Add bread mode parameter to uicons.js resolvePokemonIcon
- Add specificstation blocked_alerts check in Go matcher

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Matches the convention used by egg script export and the PR.
The colon is optional when importing (regex uses :?) but consistent
output makes scripts more readable.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- GET: support ?profile_no query param override
- POST: support ?profile_no and ?silent/?suppressMessage params
- POST: use insertQuery with 'uid' returning param
- POST: return newUids, alreadyPresent, updates, insert counts
- Remove unused deep-object-diff import

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Was using old PoracleJS path (../../../../config/pokemonAlias.json).
Now uses getPokemonAlias() helper matching other commands.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The processor was sending "maxbattle" but the Golbat webhook type is
"max_battle". Changed processor outbound type and alerter dispatch to
use "max_battle" consistently. Also added missing enrichment case for
max_battle in poracle-test.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The controller was using setImmediate + this.emit('postMessage')
which was a pattern from the old worker-thread PoracleJS architecture.
In PoracleNG, no listener exists for 'postMessage' so jobs were
silently lost. Now returns jobs directly from handleMatched like
all other controllers.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Use processor-provided disappearTime/tth instead of computing
  with geoTz + moment (removed geoTz dependency)
- Use processor-provided weather data (data.gameWeatherId) instead
  of computing from weatherData service
- Fix setNightTime call signature (was passing 3 args, needs 2)
- Fix calculateForecastImpact: pass null for weatherCellId
- Restore correct static map field names (battle_pokemon_id etc.)
- Fix matchedAreas map to handle both object and string entries

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@jfberry
Copy link
Copy Markdown
Owner Author

jfberry commented Mar 21, 2026

this was merged

@jfberry jfberry closed this Mar 21, 2026
jfberry added a commit that referenced this pull request Mar 22, 2026
Worker pool deadlock (#2):
- Added context to ProcessorService. Close() cancels before Wait().
  All 9 handlers use select — no blocking at shutdown.

Response body leak (#4):
- Sender: nil-guarded defer resp.Body.Close() before error check.

Blocked alerts matching (#7):
- BlockedAlertsSet parsed from JSON at load time. O(1) map lookup
  replaces strings.Contains in 4 matching files.

Encounter tracker growth (#8):
- InsertedAt timestamp + 4-hour max age eviction for entries with
  disappearTime=0.

PVP evolution form (#11):
- Form field added to LeagueRank, preserving form ID for PVP
  evolution matching (matches original JS behaviour).

Fort change_types matching (#14):
- json.Unmarshal replaces strings.Contains on JSON text.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
jfberry added a commit that referenced this pull request Mar 23, 2026
Worker pool deadlock (#2):
- Added context to ProcessorService. Close() cancels before Wait().
  All 9 handlers use select — no blocking at shutdown.

Response body leak (#4):
- Sender: nil-guarded defer resp.Body.Close() before error check.

Blocked alerts matching (#7):
- BlockedAlertsSet parsed from JSON at load time. O(1) map lookup
  replaces strings.Contains in 4 matching files.

Encounter tracker growth (#8):
- InsertedAt timestamp + 4-hour max age eviction for entries with
  disappearTime=0.

PVP evolution form (#11):
- Form field added to LeagueRank, preserving form ID for PVP
  evolution matching (matches original JS behaviour).

Fort change_types matching (#14):
- json.Unmarshal replaces strings.Contains on JSON text.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@jfberry jfberry deleted the maxbattle branch April 9, 2026 17:29
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.

2 participants