mirror of
https://github.com/idanoo/go-flat-finder.git
synced 2024-12-04 06:03:16 +00:00
291 lines
8.6 KiB
Go
291 lines
8.6 KiB
Go
package flatfinder
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"net/url"
|
|
)
|
|
|
|
type ChorusAddressSearchResponse struct {
|
|
Results []struct {
|
|
Aid string `json:"aid"`
|
|
Label string `json:"label"`
|
|
Links []struct {
|
|
Rel string `json:"rel"`
|
|
Href string `json:"href"`
|
|
Method string `json:"method"`
|
|
} `json:"links"`
|
|
} `json:"results"`
|
|
}
|
|
|
|
type ChorusUniqueIdResponse struct {
|
|
FormattedAddress struct {
|
|
Line1 string `json:"line1"`
|
|
Line2 interface{} `json:"line2"`
|
|
Line3 string `json:"line3"`
|
|
Line4 string `json:"line4"`
|
|
} `json:"formattedAddress"`
|
|
StructuredAddress struct {
|
|
LevelNumber interface{} `json:"levelNumber"`
|
|
LevelType interface{} `json:"levelType"`
|
|
StreetNumber int `json:"streetNumber"`
|
|
SituationNumber int `json:"situationNumber"`
|
|
Suffix interface{} `json:"suffix"`
|
|
Unit interface{} `json:"unit"`
|
|
UnitType interface{} `json:"unitType"`
|
|
StreetName string `json:"streetName"`
|
|
RoadType string `json:"roadType"`
|
|
RoadAbv string `json:"roadAbv"`
|
|
RoadSuffix interface{} `json:"roadSuffix"`
|
|
Suburb string `json:"suburb"`
|
|
RuralDelivery interface{} `json:"ruralDelivery"`
|
|
Town string `json:"town"`
|
|
Postcode string `json:"postcode"`
|
|
BoxNumber interface{} `json:"boxNumber"`
|
|
BoxLobby interface{} `json:"boxLobby"`
|
|
BoxType interface{} `json:"boxType"`
|
|
Region string `json:"region"`
|
|
Country string `json:"country"`
|
|
IsPrimary string `json:"isPrimary"`
|
|
} `json:"structuredAddress"`
|
|
Location struct {
|
|
NztmX float64 `json:"nztmX"`
|
|
NztmY float64 `json:"nztmY"`
|
|
NzmgX float64 `json:"nzmgX"`
|
|
NzmgY float64 `json:"nzmgY"`
|
|
Wgs84Lat float64 `json:"wgs84Lat"`
|
|
Wgs84Lon float64 `json:"wgs84Lon"`
|
|
} `json:"location"`
|
|
References struct {
|
|
Aid string `json:"aid"`
|
|
Dpid interface{} `json:"dpid"`
|
|
Tui int `json:"tui"`
|
|
Tlc int `json:"tlc"`
|
|
Plsam int `json:"plsam"`
|
|
} `json:"references"`
|
|
Related []interface{} `json:"related"`
|
|
Links []struct {
|
|
Rel string `json:"rel"`
|
|
Href string `json:"href"`
|
|
Method string `json:"method"`
|
|
} `json:"links"`
|
|
}
|
|
|
|
type ChorusAddressLookupResponse struct {
|
|
RegionRsp string `json:"region_rsp"`
|
|
SubregionRsp string `json:"subregion_rsp"`
|
|
AreaHyperfibre string `json:"area_hyperfibre"`
|
|
AlternativeFibreProvider string `json:"alternative_fibre_provider"`
|
|
AreaFibreSupplier string `json:"area_fibre_supplier"`
|
|
PointOfInterconnect string `json:"point_of_interconnect"`
|
|
ProductZoneType string `json:"product_zone_type"`
|
|
ActiveServices []struct {
|
|
Service string `json:"service"`
|
|
SpeedMbps int `json:"speed_mbps"`
|
|
SpeedUlMbps int `json:"speed_ul_mbps"`
|
|
} `json:"active_services"`
|
|
AvailableServices []struct {
|
|
Service string `json:"service"`
|
|
ServiceIndicator string `json:"service_indicator"`
|
|
Capable string `json:"capable"`
|
|
SpeedMbps float64 `json:"speed_mbps"`
|
|
InstallLeadTimeDays string `json:"install_lead_time_days,omitempty"`
|
|
InstallLeadTimeWeeks string `json:"install_lead_time_weeks,omitempty"`
|
|
SpeedUlMbps float64 `json:"speed_ul_mbps,omitempty"`
|
|
} `json:"available_services"`
|
|
FutureServices []interface{} `json:"future_services"`
|
|
Fibre struct {
|
|
BuildRequired string `json:"build_required"`
|
|
ConsentRequired string `json:"consent_required"`
|
|
ConsentStatus string `json:"consent_status"`
|
|
DesignRequired string `json:"design_required"`
|
|
DwellingType string `json:"dwelling_type"`
|
|
FibreInADayCapable string `json:"fibre_in_a_day_capable"`
|
|
Greenfields string `json:"greenfields"`
|
|
IntactOnt string `json:"intact_ont"`
|
|
MduBuildStatus string `json:"mdu_build_status"`
|
|
MduClass string `json:"mdu_class"`
|
|
MduDesignStatus interface{} `json:"mdu_design_status"`
|
|
PermitDelayLikely string `json:"permit_delay_likely"`
|
|
RightOfWay string `json:"right_of_way"`
|
|
} `json:"fibre"`
|
|
Copper struct {
|
|
PremiseWiringRecommended string `json:"premise_wiring_recommended"`
|
|
} `json:"copper"`
|
|
}
|
|
|
|
// getAvailableSpeeds - Checks if VDSL/FIBRE is available
|
|
func getAvailableSpeeds(address string) (string, string) {
|
|
aid, err := chorusAddressLookup(address)
|
|
if err != nil {
|
|
log.Print(err)
|
|
return "UNK", "UNK"
|
|
}
|
|
// log.Printf("Using AID: %s", aid)
|
|
|
|
tlc, err := chorusGetUnqiueID(aid)
|
|
if err != nil {
|
|
log.Print(err)
|
|
return "UNK", "UNK"
|
|
}
|
|
// log.Printf("Using TLC: %d", tlc)
|
|
|
|
chorusURL := fmt.Sprintf("https://www.chorus.co.nz/api/bbc/bcc/%d", tlc)
|
|
client := http.Client{}
|
|
req, err := http.NewRequest("GET", chorusURL, nil)
|
|
if err != nil {
|
|
log.Print(err)
|
|
return "UNK", "UNK"
|
|
}
|
|
|
|
// Do the request
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
log.Print(err)
|
|
return "UNK", "UNK"
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode == http.StatusOK {
|
|
bodyBytes, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
log.Print(err)
|
|
return "UNK", "UNK"
|
|
}
|
|
|
|
// Decode JSON
|
|
var chorusResult ChorusAddressLookupResponse
|
|
err = json.Unmarshal(bodyBytes, &chorusResult)
|
|
if err != nil {
|
|
log.Print(err)
|
|
return "UNK", "UNK"
|
|
}
|
|
|
|
hasFibre := "No"
|
|
if chorusResult.Fibre.BuildRequired == "N" {
|
|
hasFibre = "Yes"
|
|
}
|
|
|
|
maxSpeed := 0.0
|
|
for _, available := range chorusResult.AvailableServices {
|
|
if available.SpeedMbps > maxSpeed && available.Capable == "YES" {
|
|
maxSpeed = available.SpeedMbps
|
|
}
|
|
}
|
|
|
|
current := "None"
|
|
for _, active := range chorusResult.ActiveServices {
|
|
current = fmt.Sprintf("%s (%d Mbps)", active.Service, active.SpeedMbps)
|
|
}
|
|
|
|
return fmt.Sprintf("%s (%.0f Mbps)", hasFibre, maxSpeed), current
|
|
} else {
|
|
log.Print("Invalid response from API: " + resp.Status)
|
|
}
|
|
|
|
return "UNK", "UNK"
|
|
}
|
|
|
|
// chorusAddressLookup - Try get the AID for the address
|
|
func chorusAddressLookup(address string) (string, error) {
|
|
lookupURL := fmt.Sprintf(
|
|
"https://api.chorus.co.nz/addresslookup/v1/addresses/?fuzzy=true&q=%s",
|
|
url.QueryEscape(address),
|
|
)
|
|
|
|
// Build HTTP request
|
|
client := http.Client{}
|
|
req, err := http.NewRequest("GET", lookupURL, nil)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
// Magic numbers - May need to dynamically receive these
|
|
req.Header.Set("X-Chorus-Client-Id", "82d4b4a8050c4d5e97c5f06120ef9c04")
|
|
req.Header.Set("X-Chorus-Client-Secret", "8899c64746474Cf18849c6B721b5Db51")
|
|
req.Header.Set("X-Transaction-Id", "ca5ef871-9b3f-4af4-958d-ee9c51094e08")
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
// Do the request
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
// They return a 203
|
|
if resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusNonAuthoritativeInfo {
|
|
bodyBytes, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
// Decode JSON
|
|
var chorusResult ChorusAddressSearchResponse
|
|
err = json.Unmarshal(bodyBytes, &chorusResult)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
// If we have a result, return the first one
|
|
for _, result := range chorusResult.Results {
|
|
return result.Aid, nil
|
|
}
|
|
|
|
return "", errors.New("No results found for address: " + address)
|
|
}
|
|
|
|
return "", errors.New("Invalid response from API: " + resp.Status)
|
|
}
|
|
|
|
// chorusGetUniqueID - Return ID needed to get avail services
|
|
func chorusGetUnqiueID(aid string) (int64, error) {
|
|
lookupURL := fmt.Sprintf(
|
|
"https://api.chorus.co.nz/addresslookup/v1/addresses/aid:%s",
|
|
aid,
|
|
)
|
|
|
|
// Build HTTP request
|
|
client := http.Client{}
|
|
req, err := http.NewRequest("GET", lookupURL, nil)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
// Magic numbers - May need to dynamically receive these
|
|
req.Header.Set("X-Chorus-Client-Id", "82d4b4a8050c4d5e97c5f06120ef9c04")
|
|
req.Header.Set("X-Chorus-Client-Secret", "8899c64746474Cf18849c6B721b5Db51")
|
|
req.Header.Set("X-Transaction-Id", "ca5ef871-9b3f-4af4-958d-ee9c51094e08")
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
// Do the request
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
// They return a 203
|
|
if resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusNonAuthoritativeInfo {
|
|
bodyBytes, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
// Decode JSON
|
|
var chorusResult ChorusUniqueIdResponse
|
|
err = json.Unmarshal(bodyBytes, &chorusResult)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return int64(chorusResult.References.Tlc), nil
|
|
}
|
|
|
|
return 0, errors.New("Invalid response from API: " + resp.Status)
|
|
}
|