From 215fcb2d1dff59d3cac40a6cf65938c40b61f235 Mon Sep 17 00:00:00 2001 From: James Berry Date: Sun, 25 Jan 2026 16:15:11 +0000 Subject: [PATCH] Webhooks to structures --- decoder/fort.go | 29 ++++--- decoder/gym.go | 126 +++++++++++++++++-------------- decoder/incident.go | 71 +++++++++++------- decoder/pokemon.go | 168 ++++++++++++++++++++++++----------------- decoder/pokestop.go | 179 +++++++++++++++++++++++++------------------- decoder/station.go | 68 +++++++++++------ decoder/weather.go | 51 +++++++++---- routes.go | 12 +-- 8 files changed, 421 insertions(+), 283 deletions(-) diff --git a/decoder/fort.go b/decoder/fort.go index ed28030f..cb17aa73 100644 --- a/decoder/fort.go +++ b/decoder/fort.go @@ -27,6 +27,13 @@ type FortWebhook struct { Location Location `json:"location"` } +type FortChangeWebhook struct { + ChangeType string `json:"change_type"` + EditTypes []string `json:"edit_types,omitempty"` + Old *FortWebhook `json:"old,omitempty"` + New *FortWebhook `json:"new,omitempty"` +} + type FortChange string type FortType string @@ -129,17 +136,17 @@ func CreateFortWebhooks(ctx context.Context, dbDetails db.DbDetails, ids []strin func CreateFortWebHooks(old *FortWebhook, new *FortWebhook, change FortChange) { if change == NEW { areas := MatchStatsGeofence(new.Location.Latitude, new.Location.Longitude) - hook := map[string]interface{}{ - "change_type": change.String(), - "new": new, + hook := FortChangeWebhook{ + ChangeType: change.String(), + New: new, } webhooksSender.AddMessage(webhooks.FortUpdate, hook, areas) statsCollector.UpdateFortCount(areas, new.Type, "addition") } else if change == REMOVAL { areas := MatchStatsGeofence(old.Location.Latitude, old.Location.Longitude) - hook := map[string]interface{}{ - "change_type": change.String(), - "old": old, + hook := FortChangeWebhook{ + ChangeType: change.String(), + Old: old, } webhooksSender.AddMessage(webhooks.FortUpdate, hook, areas) statsCollector.UpdateFortCount(areas, new.Type, "removal") @@ -181,11 +188,11 @@ func CreateFortWebHooks(old *FortWebhook, new *FortWebhook, change FortChange) { editTypes = append(editTypes, "location") } if len(editTypes) > 0 { - hook := map[string]interface{}{ - "change_type": change.String(), - "edit_types": editTypes, - "old": old, - "new": new, + hook := FortChangeWebhook{ + ChangeType: change.String(), + EditTypes: editTypes, + Old: old, + New: new, } webhooksSender.AddMessage(webhooks.FortUpdate, hook, areas) statsCollector.UpdateFortCount(areas, new.Type, "edit") diff --git a/decoder/gym.go b/decoder/gym.go index 4f1784fe..a1f3b06b 100644 --- a/decoder/gym.go +++ b/decoder/gym.go @@ -505,23 +505,37 @@ type GymDetailsWebhook struct { PowerUpEndTimestamp int64 `json:"power_up_end_timestamp"` ArScanEligible int64 `json:"ar_scan_eligible"` Defenders any `json:"defenders"` +} - //"id": id, - //"name": name ?? "Unknown", - //"url": url ?? "", - //"latitude": lat, - //"longitude": lon, - //"team": teamId ?? 0, - //"guard_pokemon_id": guardPokemonId ?? 0, - //"slots_available": availableSlots ?? 6, - //"ex_raid_eligible": exRaidEligible ?? 0, - //"in_battle": inBattle ?? false, - //"sponsor_id": sponsorId ?? 0, - //"partner_id": partnerId ?? 0, - //"power_up_points": powerUpPoints ?? 0, - //"power_up_level": powerUpLevel ?? 0, - //"power_up_end_timestamp": powerUpEndTimestamp ?? 0, - //"ar_scan_eligible": arScanEligible ?? 0 +type RaidWebhook struct { + GymId string `json:"gym_id"` + GymName string `json:"gym_name"` + GymUrl string `json:"gym_url"` + Latitude float64 `json:"latitude"` + Longitude float64 `json:"longitude"` + TeamId int64 `json:"team_id"` + Spawn int64 `json:"spawn"` + Start int64 `json:"start"` + End int64 `json:"end"` + Level int64 `json:"level"` + PokemonId int64 `json:"pokemon_id"` + Cp int64 `json:"cp"` + Gender int64 `json:"gender"` + Form int64 `json:"form"` + Alignment int64 `json:"alignment"` + Costume int64 `json:"costume"` + Evolution int64 `json:"evolution"` + Move1 int64 `json:"move_1"` + Move2 int64 `json:"move_2"` + ExRaidEligible int64 `json:"ex_raid_eligible"` + IsExclusive int64 `json:"is_exclusive"` + SponsorId int64 `json:"sponsor_id"` + PartnerId string `json:"partner_id"` + PowerUpPoints int64 `json:"power_up_points"` + PowerUpLevel int64 `json:"power_up_level"` + PowerUpEndTimestamp int64 `json:"power_up_end_timestamp"` + ArScanEligible int64 `json:"ar_scan_eligible"` + Rsvps json.RawMessage `json:"rsvps"` } func createGymFortWebhooks(oldGym *Gym, gym *Gym) { @@ -576,47 +590,45 @@ func createGymWebhooks(oldGym *Gym, gym *Gym, areas []geo.AreaName) { if (raidBattleTime > now && gym.RaidLevel.ValueOrZero() > 0) || (raidEndTime > now && gym.RaidPokemonId.ValueOrZero() > 0) { - raidHook := map[string]any{ - "gym_id": gym.Id, - "gym_name": func() string { - if !gym.Name.Valid { - return "Unknown" - } else { - return gym.Name.String - } - }(), - "gym_url": gym.Url.ValueOrZero(), - "latitude": gym.Lat, - "longitude": gym.Lon, - "team_id": gym.TeamId.ValueOrZero(), - "spawn": gym.RaidSpawnTimestamp.ValueOrZero(), - "start": gym.RaidBattleTimestamp.ValueOrZero(), - "end": gym.RaidEndTimestamp.ValueOrZero(), - "level": gym.RaidLevel.ValueOrZero(), - "pokemon_id": gym.RaidPokemonId.ValueOrZero(), - "cp": gym.RaidPokemonCp.ValueOrZero(), - "gender": gym.RaidPokemonGender.ValueOrZero(), - "form": gym.RaidPokemonForm.ValueOrZero(), - "alignment": gym.RaidPokemonAlignment.ValueOrZero(), - "costume": gym.RaidPokemonCostume.ValueOrZero(), - "evolution": gym.RaidPokemonEvolution.ValueOrZero(), - "move_1": gym.RaidPokemonMove1.ValueOrZero(), - "move_2": gym.RaidPokemonMove2.ValueOrZero(), - "ex_raid_eligible": gym.ExRaidEligible.ValueOrZero(), - "is_exclusive": gym.RaidIsExclusive.ValueOrZero(), - "sponsor_id": gym.SponsorId.ValueOrZero(), - "partner_id": gym.PartnerId.ValueOrZero(), - "power_up_points": gym.PowerUpPoints.ValueOrZero(), - "power_up_level": gym.PowerUpLevel.ValueOrZero(), - "power_up_end_timestamp": gym.PowerUpEndTimestamp.ValueOrZero(), - "ar_scan_eligible": gym.ArScanEligible.ValueOrZero(), - "rsvps": func() any { - if !gym.Rsvps.Valid { - return nil - } else { - return json.RawMessage(gym.Rsvps.ValueOrZero()) - } - }(), + gymName := "Unknown" + if gym.Name.Valid { + gymName = gym.Name.String + } + + var rsvps json.RawMessage + if gym.Rsvps.Valid { + rsvps = json.RawMessage(gym.Rsvps.ValueOrZero()) + } + + raidHook := RaidWebhook{ + GymId: gym.Id, + GymName: gymName, + GymUrl: gym.Url.ValueOrZero(), + Latitude: gym.Lat, + Longitude: gym.Lon, + TeamId: gym.TeamId.ValueOrZero(), + Spawn: gym.RaidSpawnTimestamp.ValueOrZero(), + Start: gym.RaidBattleTimestamp.ValueOrZero(), + End: gym.RaidEndTimestamp.ValueOrZero(), + Level: gym.RaidLevel.ValueOrZero(), + PokemonId: gym.RaidPokemonId.ValueOrZero(), + Cp: gym.RaidPokemonCp.ValueOrZero(), + Gender: gym.RaidPokemonGender.ValueOrZero(), + Form: gym.RaidPokemonForm.ValueOrZero(), + Alignment: gym.RaidPokemonAlignment.ValueOrZero(), + Costume: gym.RaidPokemonCostume.ValueOrZero(), + Evolution: gym.RaidPokemonEvolution.ValueOrZero(), + Move1: gym.RaidPokemonMove1.ValueOrZero(), + Move2: gym.RaidPokemonMove2.ValueOrZero(), + ExRaidEligible: gym.ExRaidEligible.ValueOrZero(), + IsExclusive: gym.RaidIsExclusive.ValueOrZero(), + SponsorId: gym.SponsorId.ValueOrZero(), + PartnerId: gym.PartnerId.ValueOrZero(), + PowerUpPoints: gym.PowerUpPoints.ValueOrZero(), + PowerUpLevel: gym.PowerUpLevel.ValueOrZero(), + PowerUpEndTimestamp: gym.PowerUpEndTimestamp.ValueOrZero(), + ArScanEligible: gym.ArScanEligible.ValueOrZero(), + Rsvps: rsvps, } webhooksSender.AddMessage(webhooks.Raid, raidHook, areas) diff --git a/decoder/incident.go b/decoder/incident.go index 6d2a7dce..7e5fbde5 100644 --- a/decoder/incident.go +++ b/decoder/incident.go @@ -40,6 +40,26 @@ type webhookLineup struct { Form null.Int `json:"form"` } +type IncidentWebhook struct { + Id string `json:"id"` + PokestopId string `json:"pokestop_id"` + Latitude float64 `json:"latitude"` + Longitude float64 `json:"longitude"` + PokestopName string `json:"pokestop_name"` + Url string `json:"url"` + Enabled bool `json:"enabled"` + Start int64 `json:"start"` + IncidentExpireTimestamp int64 `json:"incident_expire_timestamp"` + Expiration int64 `json:"expiration"` + DisplayType int16 `json:"display_type"` + Style int16 `json:"style"` + GruntType int16 `json:"grunt_type"` + Character int16 `json:"character"` + Updated int64 `json:"updated"` + Confirmed bool `json:"confirmed"` + Lineup []webhookLineup `json:"lineup"` +} + //-> `id` varchar(35) NOT NULL, //-> `pokestop_id` varchar(35) NOT NULL, //-> `start` int unsigned NOT NULL, @@ -160,34 +180,14 @@ func createIncidentWebhooks(ctx context.Context, db db.DbDetails, oldIncident *I stop = &Pokestop{} } - incidentHook := map[string]interface{}{ - "id": incident.Id, - "pokestop_id": incident.PokestopId, - "latitude": stop.Lat, - "longitude": stop.Lon, - "pokestop_name": func() string { - if stop.Name.Valid { - return stop.Name.String - } else { - return "Unknown" - } - }(), - "url": stop.Url.ValueOrZero(), - "enabled": stop.Enabled.ValueOrZero(), - "start": incident.StartTime, - "incident_expire_timestamp": incident.ExpirationTime, // deprecated, remove old key in the future - "expiration": incident.ExpirationTime, - "display_type": incident.DisplayType, - "style": incident.Style, - "grunt_type": incident.Character, // deprecated, remove old key in the future - "character": incident.Character, - "updated": incident.Updated, - "confirmed": incident.Confirmed, - "lineup": nil, + pokestopName := "Unknown" + if stop.Name.Valid { + pokestopName = stop.Name.String } + var lineup []webhookLineup if incident.Slot1PokemonId.Valid { - incidentHook["lineup"] = []webhookLineup{ + lineup = []webhookLineup{ { Slot: 1, PokemonId: incident.Slot1PokemonId, @@ -205,6 +205,27 @@ func createIncidentWebhooks(ctx context.Context, db db.DbDetails, oldIncident *I }, } } + + incidentHook := IncidentWebhook{ + Id: incident.Id, + PokestopId: incident.PokestopId, + Latitude: stop.Lat, + Longitude: stop.Lon, + PokestopName: pokestopName, + Url: stop.Url.ValueOrZero(), + Enabled: stop.Enabled.ValueOrZero(), + Start: incident.StartTime, + IncidentExpireTimestamp: incident.ExpirationTime, + Expiration: incident.ExpirationTime, + DisplayType: incident.DisplayType, + Style: incident.Style, + GruntType: incident.Character, + Character: incident.Character, + Updated: incident.Updated, + Confirmed: incident.Confirmed, + Lineup: lineup, + } + areas := MatchStatsGeofence(stop.Lat, stop.Lon) webhooksSender.AddMessage(webhooks.Invasion, incidentHook, areas) statsCollector.UpdateIncidentCount(areas) diff --git a/decoder/pokemon.go b/decoder/pokemon.go index 9244cc2b..27416d1c 100644 --- a/decoder/pokemon.go +++ b/decoder/pokemon.go @@ -412,81 +412,109 @@ func savePokemonRecordAsAtTime(ctx context.Context, db db.DbDetails, pokemon *Po } } -func createPokemonWebhooks(ctx context.Context, db db.DbDetails, old *Pokemon, new *Pokemon, areas []geo.AreaName) { - //nullString := func (v null.Int) interface{} { - // if !v.Valid { - // return "null" - // } - // return v.ValueOrZero() - //} +type PokemonWebhook struct { + SpawnpointId string `json:"spawnpoint_id"` + PokestopId string `json:"pokestop_id"` + PokestopName *string `json:"pokestop_name"` + EncounterId string `json:"encounter_id"` + PokemonId int16 `json:"pokemon_id"` + Latitude float64 `json:"latitude"` + Longitude float64 `json:"longitude"` + DisappearTime int64 `json:"disappear_time"` + DisappearTimeVerified bool `json:"disappear_time_verified"` + FirstSeen int64 `json:"first_seen"` + LastModifiedTime null.Int `json:"last_modified_time"` + Gender null.Int `json:"gender"` + Cp null.Int `json:"cp"` + Form null.Int `json:"form"` + Costume null.Int `json:"costume"` + IndividualAttack null.Int `json:"individual_attack"` + IndividualDefense null.Int `json:"individual_defense"` + IndividualStamina null.Int `json:"individual_stamina"` + PokemonLevel null.Int `json:"pokemon_level"` + Move1 null.Int `json:"move_1"` + Move2 null.Int `json:"move_2"` + Weight null.Float `json:"weight"` + Size null.Int `json:"size"` + Height null.Float `json:"height"` + Weather null.Int `json:"weather"` + Capture1 float64 `json:"capture_1"` + Capture2 float64 `json:"capture_2"` + Capture3 float64 `json:"capture_3"` + Shiny null.Bool `json:"shiny"` + Username null.String `json:"username"` + DisplayPokemonId null.Int `json:"display_pokemon_id"` + IsEvent int8 `json:"is_event"` + SeenType null.String `json:"seen_type"` + Pvp json.RawMessage `json:"pvp"` +} +func createPokemonWebhooks(ctx context.Context, db db.DbDetails, old *Pokemon, new *Pokemon, areas []geo.AreaName) { if old == nil || old.PokemonId != new.PokemonId || old.Weather != new.Weather || old.Cp != new.Cp { - pokemonHook := map[string]interface{}{ - "spawnpoint_id": func() string { - if !new.SpawnId.Valid { - return "None" - } - return strconv.FormatInt(new.SpawnId.ValueOrZero(), 16) - }(), - "pokestop_id": func() string { - if !new.PokestopId.Valid { - return "None" - } else { - return new.PokestopId.ValueOrZero() - } - }(), - "pokestop_name": func() *string { - if !new.PokestopId.Valid { - return nil - } else { - pokestop, _ := GetPokestopRecord(ctx, db, new.PokestopId.String) - name := "Unknown" - if pokestop != nil { - name = pokestop.Name.ValueOrZero() - } - return &name - } - }(), - "encounter_id": strconv.FormatUint(new.Id, 10), - "pokemon_id": new.PokemonId, - "latitude": new.Lat, - "longitude": new.Lon, - "disappear_time": new.ExpireTimestamp.ValueOrZero(), - "disappear_time_verified": new.ExpireTimestampVerified, - "first_seen": new.FirstSeenTimestamp, - "last_modified_time": new.Updated, - "gender": new.Gender, - "cp": new.Cp, - "form": new.Form, - "costume": new.Costume, - "individual_attack": new.AtkIv, - "individual_defense": new.DefIv, - "individual_stamina": new.StaIv, - "pokemon_level": new.Level, - "move_1": new.Move1, - "move_2": new.Move2, - "weight": new.Weight, - "size": new.Size, - "height": new.Height, - "weather": new.Weather, - "capture_1": new.Capture1.ValueOrZero(), - "capture_2": new.Capture2.ValueOrZero(), - "capture_3": new.Capture3.ValueOrZero(), - "shiny": new.Shiny, - "username": new.Username, - "display_pokemon_id": new.DisplayPokemonId, - "is_event": new.IsEvent, - "seen_type": new.SeenType, - "pvp": func() interface{} { - if !new.Pvp.Valid { - return nil - } else { - return json.RawMessage(new.Pvp.ValueOrZero()) - } - }(), + + spawnpointId := "None" + if new.SpawnId.Valid { + spawnpointId = strconv.FormatInt(new.SpawnId.ValueOrZero(), 16) + } + + pokestopId := "None" + if new.PokestopId.Valid { + pokestopId = new.PokestopId.ValueOrZero() + } + + var pokestopName *string + if new.PokestopId.Valid { + pokestop, _ := GetPokestopRecord(ctx, db, new.PokestopId.String) + name := "Unknown" + if pokestop != nil { + name = pokestop.Name.ValueOrZero() + } + pokestopName = &name + } + + var pvp json.RawMessage + if new.Pvp.Valid { + pvp = json.RawMessage(new.Pvp.ValueOrZero()) + } + + pokemonHook := PokemonWebhook{ + SpawnpointId: spawnpointId, + PokestopId: pokestopId, + PokestopName: pokestopName, + EncounterId: strconv.FormatUint(new.Id, 10), + PokemonId: new.PokemonId, + Latitude: new.Lat, + Longitude: new.Lon, + DisappearTime: new.ExpireTimestamp.ValueOrZero(), + DisappearTimeVerified: new.ExpireTimestampVerified, + FirstSeen: new.FirstSeenTimestamp, + LastModifiedTime: new.Updated, + Gender: new.Gender, + Cp: new.Cp, + Form: new.Form, + Costume: new.Costume, + IndividualAttack: new.AtkIv, + IndividualDefense: new.DefIv, + IndividualStamina: new.StaIv, + PokemonLevel: new.Level, + Move1: new.Move1, + Move2: new.Move2, + Weight: new.Weight, + Size: new.Size, + Height: new.Height, + Weather: new.Weather, + Capture1: new.Capture1.ValueOrZero(), + Capture2: new.Capture2.ValueOrZero(), + Capture3: new.Capture3.ValueOrZero(), + Shiny: new.Shiny, + Username: new.Username, + DisplayPokemonId: new.DisplayPokemonId, + IsEvent: new.IsEvent, + SeenType: new.SeenType, + Pvp: pvp, } if new.AtkIv.Valid && new.DefIv.Valid && new.StaIv.Valid { diff --git a/decoder/pokestop.go b/decoder/pokestop.go index ee7e966c..d6dbba86 100644 --- a/decoder/pokestop.go +++ b/decoder/pokestop.go @@ -108,6 +108,47 @@ type Pokestop struct { } +type QuestWebhook struct { + PokestopId string `json:"pokestop_id"` + Latitude float64 `json:"latitude"` + Longitude float64 `json:"longitude"` + PokestopName string `json:"pokestop_name"` + Type null.Int `json:"type"` + Target null.Int `json:"target"` + Template null.String `json:"template"` + Title null.String `json:"title"` + Conditions json.RawMessage `json:"conditions"` + Rewards json.RawMessage `json:"rewards"` + Updated int64 `json:"updated"` + ArScanEligible int64 `json:"ar_scan_eligible"` + PokestopUrl string `json:"pokestop_url"` + WithAr bool `json:"with_ar"` +} + +type PokestopWebhook struct { + PokestopId string `json:"pokestop_id"` + Latitude float64 `json:"latitude"` + Longitude float64 `json:"longitude"` + Name string `json:"name"` + Url string `json:"url"` + LureExpiration int64 `json:"lure_expiration"` + LastModified int64 `json:"last_modified"` + Enabled bool `json:"enabled"` + LureId int16 `json:"lure_id"` + ArScanEligible int64 `json:"ar_scan_eligible"` + PowerUpLevel int64 `json:"power_up_level"` + PowerUpPoints int64 `json:"power_up_points"` + PowerUpEndTimestamp int64 `json:"power_up_end_timestamp"` + Updated int64 `json:"updated"` + ShowcaseFocus null.String `json:"showcase_focus"` + ShowcasePokemonId null.Int `json:"showcase_pokemon_id"` + ShowcasePokemonFormId null.Int `json:"showcase_pokemon_form_id"` + ShowcasePokemonTypeId null.Int `json:"showcase_pokemon_type_id"` + ShowcaseRankingStandard null.Int `json:"showcase_ranking_standard"` + ShowcaseExpiry null.Int `json:"showcase_expiry"` + ShowcaseRankings json.RawMessage `json:"showcase_rankings"` +} + func GetPokestopRecord(ctx context.Context, db db.DbDetails, fortId string) (*Pokestop, error) { stop := pokestopCache.Get(fortId) if stop != nil { @@ -663,92 +704,78 @@ func createPokestopWebhooks(oldStop *Pokestop, stop *Pokestop) { areas := MatchStatsGeofence(stop.Lat, stop.Lon) + pokestopName := "Unknown" + if stop.Name.Valid { + pokestopName = stop.Name.String + } + if stop.AlternativeQuestType.Valid && (oldStop == nil || stop.AlternativeQuestType != oldStop.AlternativeQuestType) { - questHook := map[string]any{ - "pokestop_id": stop.Id, - "latitude": stop.Lat, - "longitude": stop.Lon, - "pokestop_name": func() string { - if stop.Name.Valid { - return stop.Name.String - } else { - return "Unknown" - } - }(), - "type": stop.AlternativeQuestType, - "target": stop.AlternativeQuestTarget, - "template": stop.AlternativeQuestTemplate, - "title": stop.AlternativeQuestTitle, - "conditions": json.RawMessage(stop.AlternativeQuestConditions.ValueOrZero()), - "rewards": json.RawMessage(stop.AlternativeQuestRewards.ValueOrZero()), - "updated": stop.Updated, - "ar_scan_eligible": stop.ArScanEligible.ValueOrZero(), - "pokestop_url": stop.Url.ValueOrZero(), - "with_ar": false, + questHook := QuestWebhook{ + PokestopId: stop.Id, + Latitude: stop.Lat, + Longitude: stop.Lon, + PokestopName: pokestopName, + Type: stop.AlternativeQuestType, + Target: stop.AlternativeQuestTarget, + Template: stop.AlternativeQuestTemplate, + Title: stop.AlternativeQuestTitle, + Conditions: json.RawMessage(stop.AlternativeQuestConditions.ValueOrZero()), + Rewards: json.RawMessage(stop.AlternativeQuestRewards.ValueOrZero()), + Updated: stop.Updated, + ArScanEligible: stop.ArScanEligible.ValueOrZero(), + PokestopUrl: stop.Url.ValueOrZero(), + WithAr: false, } webhooksSender.AddMessage(webhooks.Quest, questHook, areas) } if stop.QuestType.Valid && (oldStop == nil || stop.QuestType != oldStop.QuestType) { - questHook := map[string]any{ - "pokestop_id": stop.Id, - "latitude": stop.Lat, - "longitude": stop.Lon, - "pokestop_name": func() string { - if stop.Name.Valid { - return stop.Name.String - } else { - return "Unknown" - } - }(), - "type": stop.QuestType, - "target": stop.QuestTarget, - "template": stop.QuestTemplate, - "title": stop.QuestTitle, - "conditions": json.RawMessage(stop.QuestConditions.ValueOrZero()), - "rewards": json.RawMessage(stop.QuestRewards.ValueOrZero()), - "updated": stop.Updated, - "ar_scan_eligible": stop.ArScanEligible.ValueOrZero(), - "pokestop_url": stop.Url.ValueOrZero(), - "with_ar": true, + questHook := QuestWebhook{ + PokestopId: stop.Id, + Latitude: stop.Lat, + Longitude: stop.Lon, + PokestopName: pokestopName, + Type: stop.QuestType, + Target: stop.QuestTarget, + Template: stop.QuestTemplate, + Title: stop.QuestTitle, + Conditions: json.RawMessage(stop.QuestConditions.ValueOrZero()), + Rewards: json.RawMessage(stop.QuestRewards.ValueOrZero()), + Updated: stop.Updated, + ArScanEligible: stop.ArScanEligible.ValueOrZero(), + PokestopUrl: stop.Url.ValueOrZero(), + WithAr: true, } webhooksSender.AddMessage(webhooks.Quest, questHook, areas) } if (oldStop == nil && (stop.LureId != 0 || stop.PowerUpEndTimestamp.ValueOrZero() != 0)) || (oldStop != nil && ((stop.LureExpireTimestamp != oldStop.LureExpireTimestamp && stop.LureId != 0) || stop.PowerUpEndTimestamp != oldStop.PowerUpEndTimestamp)) { - pokestopHook := map[string]any{ - "pokestop_id": stop.Id, - "latitude": stop.Lat, - "longitude": stop.Lon, - "name": func() string { - if stop.Name.Valid { - return stop.Name.String - } else { - return "Unknown" - } - }(), - "url": stop.Url.ValueOrZero(), - "lure_expiration": stop.LureExpireTimestamp.ValueOrZero(), - "last_modified": stop.LastModifiedTimestamp.ValueOrZero(), - "enabled": stop.Enabled.ValueOrZero(), - "lure_id": stop.LureId, - "ar_scan_eligible": stop.ArScanEligible.ValueOrZero(), - "power_up_level": stop.PowerUpLevel.ValueOrZero(), - "power_up_points": stop.PowerUpPoints.ValueOrZero(), - "power_up_end_timestamp": stop.PowerUpPoints.ValueOrZero(), - "updated": stop.Updated, - "showcase_focus": stop.ShowcaseFocus, - "showcase_pokemon_id": stop.ShowcasePokemon, - "showcase_pokemon_form_id": stop.ShowcasePokemonForm, - "showcase_pokemon_type_id": stop.ShowcasePokemonType, - "showcase_ranking_standard": stop.ShowcaseRankingStandard, - "showcase_expiry": stop.ShowcaseExpiry, - "showcase_rankings": func() any { - if !stop.ShowcaseRankings.Valid { - return nil - } else { - return json.RawMessage(stop.ShowcaseRankings.ValueOrZero()) - } - }(), + var showcaseRankings json.RawMessage + if stop.ShowcaseRankings.Valid { + showcaseRankings = json.RawMessage(stop.ShowcaseRankings.ValueOrZero()) + } + + pokestopHook := PokestopWebhook{ + PokestopId: stop.Id, + Latitude: stop.Lat, + Longitude: stop.Lon, + Name: pokestopName, + Url: stop.Url.ValueOrZero(), + LureExpiration: stop.LureExpireTimestamp.ValueOrZero(), + LastModified: stop.LastModifiedTimestamp.ValueOrZero(), + Enabled: stop.Enabled.ValueOrZero(), + LureId: stop.LureId, + ArScanEligible: stop.ArScanEligible.ValueOrZero(), + PowerUpLevel: stop.PowerUpLevel.ValueOrZero(), + PowerUpPoints: stop.PowerUpPoints.ValueOrZero(), + PowerUpEndTimestamp: stop.PowerUpPoints.ValueOrZero(), + Updated: stop.Updated, + ShowcaseFocus: stop.ShowcaseFocus, + ShowcasePokemonId: stop.ShowcasePokemon, + ShowcasePokemonFormId: stop.ShowcasePokemonForm, + ShowcasePokemonTypeId: stop.ShowcasePokemonType, + ShowcaseRankingStandard: stop.ShowcaseRankingStandard, + ShowcaseExpiry: stop.ShowcaseExpiry, + ShowcaseRankings: showcaseRankings, } webhooksSender.AddMessage(webhooks.Pokestop, pokestopHook, areas) diff --git a/decoder/station.go b/decoder/station.go index 34b0de81..f02b46f1 100644 --- a/decoder/station.go +++ b/decoder/station.go @@ -49,6 +49,30 @@ type Station struct { StationedPokemon null.String `db:"stationed_pokemon"` } +type StationWebhook struct { + Id string `json:"id"` + Latitude float64 `json:"latitude"` + Longitude float64 `json:"longitude"` + Name string `json:"name"` + StartTime int64 `json:"start_time"` + EndTime int64 `json:"end_time"` + IsBattleAvailable bool `json:"is_battle_available"` + BattleLevel null.Int `json:"battle_level"` + BattleStart null.Int `json:"battle_start"` + BattleEnd null.Int `json:"battle_end"` + BattlePokemonId null.Int `json:"battle_pokemon_id"` + BattlePokemonForm null.Int `json:"battle_pokemon_form"` + BattlePokemonCostume null.Int `json:"battle_pokemon_costume"` + BattlePokemonGender null.Int `json:"battle_pokemon_gender"` + BattlePokemonAlignment null.Int `json:"battle_pokemon_alignment"` + BattlePokemonBreadMode null.Int `json:"battle_pokemon_bread_mode"` + BattlePokemonMove1 null.Int `json:"battle_pokemon_move_1"` + BattlePokemonMove2 null.Int `json:"battle_pokemon_move_2"` + TotalStationedPokemon null.Int `json:"total_stationed_pokemon"` + TotalStationedGmax null.Int `json:"total_stationed_gmax"` + Updated int64 `json:"updated"` +} + func getStationRecord(ctx context.Context, db db.DbDetails, stationId string) (*Station, error) { inMemoryStation := stationCache.Get(stationId) if inMemoryStation != nil { @@ -317,28 +341,28 @@ func createStationWebhooks(oldStation *Station, station *Station) { oldStation.BattlePokemonCostume != station.BattlePokemonCostume || oldStation.BattlePokemonGender != station.BattlePokemonGender || oldStation.BattlePokemonBreadMode != station.BattlePokemonBreadMode) { - stationHook := map[string]any{ - "id": station.Id, - "latitude": station.Lat, - "longitude": station.Lon, - "name": station.Name, - "start_time": station.StartTime, - "end_time": station.EndTime, - "is_battle_available": station.IsBattleAvailable, - "battle_level": station.BattleLevel, - "battle_start": station.BattleStart, - "battle_end": station.BattleEnd, - "battle_pokemon_id": station.BattlePokemonId, - "battle_pokemon_form": station.BattlePokemonForm, - "battle_pokemon_costume": station.BattlePokemonCostume, - "battle_pokemon_gender": station.BattlePokemonGender, - "battle_pokemon_alignment": station.BattlePokemonAlignment, - "battle_pokemon_bread_mode": station.BattlePokemonBreadMode, - "battle_pokemon_move_1": station.BattlePokemonMove1, - "battle_pokemon_move_2": station.BattlePokemonMove2, - "total_stationed_pokemon": station.TotalStationedPokemon, - "total_stationed_gmax": station.TotalStationedGmax, - "updated": station.Updated, + stationHook := StationWebhook{ + Id: station.Id, + Latitude: station.Lat, + Longitude: station.Lon, + Name: station.Name, + StartTime: station.StartTime, + EndTime: station.EndTime, + IsBattleAvailable: station.IsBattleAvailable, + BattleLevel: station.BattleLevel, + BattleStart: station.BattleStart, + BattleEnd: station.BattleEnd, + BattlePokemonId: station.BattlePokemonId, + BattlePokemonForm: station.BattlePokemonForm, + BattlePokemonCostume: station.BattlePokemonCostume, + BattlePokemonGender: station.BattlePokemonGender, + BattlePokemonAlignment: station.BattlePokemonAlignment, + BattlePokemonBreadMode: station.BattlePokemonBreadMode, + BattlePokemonMove1: station.BattlePokemonMove1, + BattlePokemonMove2: station.BattlePokemonMove2, + TotalStationedPokemon: station.TotalStationedPokemon, + TotalStationedGmax: station.TotalStationedGmax, + Updated: station.Updated, } areas := MatchStatsGeofence(station.Lat, station.Lon) webhooksSender.AddMessage(webhooks.MaxBattle, stationHook, areas) diff --git a/decoder/weather.go b/decoder/weather.go index ae5aa573..3e29aa24 100644 --- a/decoder/weather.go +++ b/decoder/weather.go @@ -122,6 +122,24 @@ func hasChangesWeather(old *Weather, new *Weather) bool { !floatAlmostEqual(old.Longitude, new.Longitude, floatTolerance) } +type WeatherWebhook struct { + S2CellId int64 `json:"s2_cell_id"` + Latitude float64 `json:"latitude"` + Longitude float64 `json:"longitude"` + Polygon [4][2]float64 `json:"polygon"` + GameplayCondition int64 `json:"gameplay_condition"` + WindDirection int64 `json:"wind_direction"` + CloudLevel int64 `json:"cloud_level"` + RainLevel int64 `json:"rain_level"` + WindLevel int64 `json:"wind_level"` + SnowLevel int64 `json:"snow_level"` + FogLevel int64 `json:"fog_level"` + SpecialEffectLevel int64 `json:"special_effect_level"` + Severity int64 `json:"severity"` + WarnWeather bool `json:"warn_weather"` + Updated int64 `json:"updated"` +} + func createWeatherWebhooks(oldWeather *Weather, weather *Weather) { if oldWeather == nil || oldWeather.GameplayCondition.ValueOrZero() != weather.GameplayCondition.ValueOrZero() || oldWeather.WarnWeather.ValueOrZero() != weather.WarnWeather.ValueOrZero() { @@ -133,22 +151,23 @@ func createWeatherWebhooks(oldWeather *Weather, weather *Weather) { latLng := s2.LatLngFromPoint(vertex) polygon[i] = [...]float64{latLng.Lat.Degrees(), latLng.Lng.Degrees()} } - weatherHook := map[string]interface{}{ - "s2_cell_id": weather.Id, - "latitude": weather.Latitude, - "longitude": weather.Longitude, - "polygon": polygon, - "gameplay_condition": weather.GameplayCondition.ValueOrZero(), - "wind_direction": weather.WindDirection.ValueOrZero(), - "cloud_level": weather.CloudLevel.ValueOrZero(), - "rain_level": weather.RainLevel.ValueOrZero(), - "wind_level": weather.WindLevel.ValueOrZero(), - "snow_level": weather.SnowLevel.ValueOrZero(), - "fog_level": weather.FogLevel.ValueOrZero(), - "special_effect_level": weather.SpecialEffectLevel.ValueOrZero(), - "severity": weather.Severity.ValueOrZero(), - "warn_weather": weather.WarnWeather.ValueOrZero(), - "updated": weather.UpdatedMs / 1000, + + weatherHook := WeatherWebhook{ + S2CellId: weather.Id, + Latitude: weather.Latitude, + Longitude: weather.Longitude, + Polygon: polygon, + GameplayCondition: weather.GameplayCondition.ValueOrZero(), + WindDirection: weather.WindDirection.ValueOrZero(), + CloudLevel: weather.CloudLevel.ValueOrZero(), + RainLevel: weather.RainLevel.ValueOrZero(), + WindLevel: weather.WindLevel.ValueOrZero(), + SnowLevel: weather.SnowLevel.ValueOrZero(), + FogLevel: weather.FogLevel.ValueOrZero(), + SpecialEffectLevel: weather.SpecialEffectLevel.ValueOrZero(), + Severity: weather.Severity.ValueOrZero(), + WarnWeather: weather.WarnWeather.ValueOrZero(), + Updated: weather.UpdatedMs / 1000, } areas := MatchStatsGeofence(weather.Latitude, weather.Longitude) webhooksSender.AddMessage(webhooks.Weather, weatherHook, areas) diff --git a/routes.go b/routes.go index e68c16a6..ca840480 100644 --- a/routes.go +++ b/routes.go @@ -40,6 +40,10 @@ type InboundRawData struct { HaveAr *bool } +type StatusResponse struct { + Status string `json:"status"` +} + func questsHeldHasARTask(quests_held any) *bool { const ar_quest_id = int64(pogo.QuestType_QUEST_GEOTARGETED_AR_SCAN) @@ -346,17 +350,13 @@ func ClearQuests(c *gin.Context) { decoder.ClearQuestsWithinGeofence(ctx, dbDetails, fence) log.Infof("Clear quest took %s", time.Since(startTime)) - c.JSON(http.StatusAccepted, map[string]interface{}{ - "status": "ok", - }) + c.JSON(http.StatusAccepted, StatusResponse{Status: "ok"}) } func ReloadGeojson(c *gin.Context) { decoder.ReloadGeofenceAndClearStats() - c.JSON(http.StatusAccepted, map[string]interface{}{ - "status": "ok", - }) + c.JSON(http.StatusAccepted, StatusResponse{Status: "ok"}) } func PokemonScan(c *gin.Context) {