| 1. Webhook source โ new event type, or piggyback on an existing handler? | If new: add struct + receiver case + handler. If piggyback: extend the existing handler to fan out to the new matcher; skip the receiver work. | New: cmd/processor/maxbattle.go + webhook/receiver.go:115. Piggyback: see how gym and gym_details share case "gym", "gym_details": at receiver.go:103. |
| 2. Pokemon-by-ID filter โ does the rule say "this pokemon" / "any pokemon"? | Adds pokemon_id column with 9000 sentinel = "any". Adds pokemon-resolver wiring in the bot command + tests. | db/maxbattle.go (column default 9000), bot/commands/maxbattle.go (uses ctx.Resolver), matching/maxbattle.go (skip filter when 9000). |
| 3. Form-aware โ does form matter (e.g. Alolan vs normal)? | Adds form column (default 0). Pokemon resolver is already form-aware. | db/maxbattle.go, matching/maxbattle.go. |
| 4. Numeric range filters โ IV / level / CP / similar? | Per-range pair of columns with 9000/-1/0 sentinels. | db/monsters.go (IV/CP/level pairs). For a single threshold see db/maxbattle.go:level. |
| 5. List filters โ type IDs, move IDs, item IDs as a multi-select? | Stored as JSON-encoded array in a TEXT column; matcher does json.Unmarshal and slices.Contains. | db/forts.go:ChangeTypes + matching/fort.go:changeTypesMatch. Don't store comma-separated โ the silent dedup bug at fort.go showed why. |
| 6. Time-bound expiry โ does the alert have a "fires until" timestamp? | Enrichment computes tth and disappearTime via geo.ComputeTTH + geo.FormatTime. Templates can use {{tthm}}:{{tths}}. Affects clean/edit semantics (next row). | enrichment/raid.go, enrichment/maxbattle.go. |
| 7. Edit support โ should the same event update an existing message rather than send a new one (e.g. RSVP changes, contest entry counts, ranking shifts)? | Adds clean bit 2 = "edit"; renderer generates a stable EditKey per event; delivery.FairQueue looks up MessageTracker and edits in place if found. | db/clean.go (bitmask), cmd/processor/raid.go (EditKey derivation per type), delivery/tracker.go (MessageTracker lookup), dts.RenderJob.EditKey, the rsvp_changes column in db/raid.go. This is a non-trivial design decision โ discuss the EditKey shape with the user (what fields make a "same alert"?). |
| 8. Auto-delete on TTH โ should the message be deleted when the event ends? | Adds clean bit 1 = "clean". MessageTracker schedules a deletion callback at tth. Implies #6 (must have an expiry). | Same files as #7; the bit is independent โ a rule can be edit+clean (3) or just one or neither. |
| 9. Multi-rule per user with metadata โ can one user legitimately match the same event multiple times with different rule context (cf. pokemon PVP great + ultra leagues both matching)? | Matcher does not dedup by user ID; per-user enrichment merges entries. | matching/pokemon.go + enrichment/peruser.go::consolidateUsers. Most types should dedup; this is the rare exception. |
| 10. Bound to a fixed POI โ stop, gym, station, nest? | Stores *_id text column with default NULL/empty meaning "any of this POI type". | db/maxbattle.go:station_id, db/raid.go:gym_id, db/nests.go:nest_id. |
| 11. Per-type tile / icon โ does the static map need a custom tileserver template, or use a custom fallback img? | Add tileserver_templates/<set>/poracle-$0.json (per tile-set: rampardos, swifttileserver-night, etc.) and optionally a new Fallbacks.ImgURL$0 field. | tileserver_templates/rampardos/poracle-monster.json for tile shape; config.go:FallbacksConfig + config_schema.go:489 for fallback wiring. |
12. Pokemon-resolver in command โ does !$0 pikachu need to resolve the pokemon name? | Use ctx.Resolver in the bot command; reuse parameterDefinition-style arg parsing from commands/track.go. | bot/commands/maxbattle.go, bot/pokemon_resolver.go, bot/argmatch.go. |
| 13. Repeat-firing webhook โ does Golbat re-emit the same event multiple times (every minute / every scan) so we need version-aware dedup? | Dedup key includes a version / AR / timestamp field, not just IDs. | cmd/processor/quest.go::buildQuestRewardsKey (with the AR prefix), tracker/duplicate.go::CheckQuest. |
14. Validation hook participation โ should an outbound HTTP validator be called per matched user before enrichment (the existing [validation] url mechanism)? | No new code โ the hook fires for any type whose matcher returns matches. Just verify the type label is plumbed through filterValidation. | cmd/processor/quest.go:71 and the implementation in validation/. |
| 15. Translation requirements โ does the rendered alert need translated pokemon / type / move / weather names? | Add a $0Translate per-language enrichment function. | enrichment/maxbattle.go::MaxbattleTranslate. |