|
1 | 1 | package spot |
2 | 2 |
|
3 | 3 | import ( |
| 4 | + "encoding/json" |
| 5 | + "fmt" |
4 | 6 | "time" |
5 | 7 |
|
6 | 8 | "github.com/user00265/dxclustergoapi/internal/dxcc" |
@@ -35,6 +37,75 @@ type Spot struct { |
35 | 37 | } `json:"additional_data,omitempty"` |
36 | 38 | } |
37 | 39 |
|
| 40 | +// MarshalJSON customizes the JSON output to match the expected API format |
| 41 | +func (s Spot) MarshalJSON() ([]byte, error) { |
| 42 | + // Helper to build the flattened DXCC+LoTW object |
| 43 | + type FlatInfo struct { |
| 44 | + Cont string `json:"cont,omitempty"` |
| 45 | + Entity string `json:"entity,omitempty"` |
| 46 | + Flag string `json:"flag,omitempty"` |
| 47 | + DXCCID interface{} `json:"dxcc_id,omitempty"` // string in output |
| 48 | + LoTWUser interface{} `json:"lotw_user"` // "2" or false |
| 49 | + Lat interface{} `json:"lat,omitempty"` // string in output |
| 50 | + Lng interface{} `json:"lng,omitempty"` // string in output |
| 51 | + } |
| 52 | + |
| 53 | + buildFlatInfo := func(info Info) *FlatInfo { |
| 54 | + flat := &FlatInfo{} |
| 55 | + if info.DXCC != nil { |
| 56 | + flat.Cont = info.DXCC.Cont |
| 57 | + flat.Entity = info.DXCC.Entity |
| 58 | + flat.Flag = info.DXCC.Flag |
| 59 | + // Convert numbers to strings to match expected format |
| 60 | + if info.DXCC.DXCCID != 0 { |
| 61 | + flat.DXCCID = fmt.Sprintf("%d", info.DXCC.DXCCID) |
| 62 | + } |
| 63 | + if info.DXCC.Latitude != 0 { |
| 64 | + flat.Lat = fmt.Sprintf("%.1f", info.DXCC.Latitude) |
| 65 | + } |
| 66 | + if info.DXCC.Longitude != 0 { |
| 67 | + flat.Lng = fmt.Sprintf("%.1f", info.DXCC.Longitude) |
| 68 | + } |
| 69 | + } |
| 70 | + // LoTW user: "2" if user, false if not |
| 71 | + if info.IsLoTWUser && info.LoTW != nil { |
| 72 | + flat.LoTWUser = "2" // Indicates LoTW user with upload |
| 73 | + } else { |
| 74 | + flat.LoTWUser = false |
| 75 | + } |
| 76 | + return flat |
| 77 | + } |
| 78 | + |
| 79 | + // Build the output structure - simple keys first, then objects |
| 80 | + output := struct { |
| 81 | + Spotter string `json:"spotter"` |
| 82 | + Spotted string `json:"spotted"` |
| 83 | + Frequency float64 `json:"frequency"` |
| 84 | + Band string `json:"band"` |
| 85 | + Message string `json:"message"` |
| 86 | + When time.Time `json:"when"` |
| 87 | + Source string `json:"source,omitempty"` // Extra: helpful for debugging |
| 88 | + PotaRef string `json:"pota_ref,omitempty"` // Extra: POTA reference (only for POTA spots) |
| 89 | + PotaMode string `json:"pota_mode,omitempty"` // Extra: POTA mode (only for POTA spots) |
| 90 | + DXCCSpotter *FlatInfo `json:"dxcc_spotter,omitempty"` |
| 91 | + DXCCSpotted *FlatInfo `json:"dxcc_spotted,omitempty"` |
| 92 | + }{ |
| 93 | + Spotter: s.Spotter, |
| 94 | + Spotted: s.Spotted, |
| 95 | + Frequency: s.Frequency, |
| 96 | + Band: s.Band, |
| 97 | + Message: s.Message, |
| 98 | + When: s.When, |
| 99 | + Source: s.Source, |
| 100 | + PotaRef: s.AdditionalData.PotaRef, |
| 101 | + PotaMode: s.AdditionalData.PotaMode, |
| 102 | + DXCCSpotter: buildFlatInfo(s.SpotterInfo), |
| 103 | + DXCCSpotted: buildFlatInfo(s.SpottedInfo), |
| 104 | + } |
| 105 | + |
| 106 | + return json.Marshal(output) |
| 107 | +} |
| 108 | + |
38 | 109 | // BandFromName converts a frequency to a ham radio band string. |
39 | 110 | // Accepts frequency in Hz, kHz, or MHz and automatically detects the unit. |
40 | 111 | // This function mirrors the qrg2band from the Node.js original. |
|
0 commit comments