mirror of
https://github.com/idanoo/go-flat-finder.git
synced 2024-12-03 13:43:14 +00:00
Working internet speeds
This commit is contained in:
parent
9927075d15
commit
a87f8e21fe
13
flatfinder.service
Normal file
13
flatfinder.service
Normal file
@ -0,0 +1,13 @@
|
||||
[Unit]
|
||||
Description=FlatFinder
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/root/flatfinder
|
||||
WorkingDirectory=/root
|
||||
Type=simple
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
4
go.mod
4
go.mod
@ -3,7 +3,6 @@ module flatfinder
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
github.com/bwmarrin/discordgo v0.26.1
|
||||
github.com/disgoorg/disgo v0.13.19
|
||||
github.com/disgoorg/snowflake/v2 v2.0.0
|
||||
github.com/joho/godotenv v1.4.0
|
||||
@ -11,8 +10,5 @@ require (
|
||||
|
||||
require (
|
||||
github.com/disgoorg/log v1.2.0 // indirect
|
||||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b // indirect
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b // indirect
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 // indirect
|
||||
)
|
||||
|
13
go.sum
13
go.sum
@ -1,5 +1,3 @@
|
||||
github.com/bwmarrin/discordgo v0.26.1 h1:AIrM+g3cl+iYBr4yBxCBp9tD9jR3K7upEjl0d89FRkE=
|
||||
github.com/bwmarrin/discordgo v0.26.1/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/disgoorg/disgo v0.13.19 h1:evbkWRQ9fU3dIrRJnl+jFTt55cKAeeEwnB/Q3dqgz20=
|
||||
github.com/disgoorg/disgo v0.13.19/go.mod h1:Cyip4bCYHD3rHgDhBPT9cLo81e9AMbDe8ocM50UNRM4=
|
||||
@ -7,21 +5,10 @@ github.com/disgoorg/log v1.2.0 h1:sqlXnu/ZKAlIlHV9IO+dbMto7/hCQ474vlIdMWk8QKo=
|
||||
github.com/disgoorg/log v1.2.0/go.mod h1:3x1KDG6DI1CE2pDwi3qlwT3wlXpeHW/5rVay+1qDqOo=
|
||||
github.com/disgoorg/snowflake/v2 v2.0.0 h1:+xvyyDddXmXLHmiG8SZiQ3sdZdZPbUR22fSHoqwkrOA=
|
||||
github.com/disgoorg/snowflake/v2 v2.0.0/go.mod h1:SPU9c2CNn5DSyb86QcKtdZgix9osEtKrHLW4rMhfLCs=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg=
|
||||
github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b h1:qYTY2tN72LhgDj2rtWG+LI6TXFl2ygFQQ4YezfVaGQE=
|
||||
github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b/go.mod h1:/pA7k3zsXKdjjAiUhB5CjuKib9KJGCaLvZwtxGC8U0s=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b h1:7mWr3k41Qtv8XlltBkDkl8LoP3mpSgBW8BUoxtEdbXg=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
|
@ -1,6 +1,8 @@
|
||||
package flatfinder
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
@ -8,92 +10,281 @@ import (
|
||||
"net/url"
|
||||
)
|
||||
|
||||
type ChorusAddressLookupResponse struct {
|
||||
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"`
|
||||
}
|
||||
|
||||
func chorusAddressLookup(address string) string {
|
||||
log.Printf("Querying address: %s", address)
|
||||
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),
|
||||
)
|
||||
//curl 'https://api.chorus.co.nz/addresslookup/v1/addresses/?fuzzy=true&q=35%20Rosalind' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:104.0) Gecko/20100101 Firefox/104.0' -H 'Accept: application/json, text/plain, */*' -H 'Accept-Language: en-US,en;q=0.5' -H 'Accept-Encoding: gzip, deflate, br' -H 'X-Chorus-Client-Id: 82d4b4a8050c4d5e97c5f06120ef9c04' -H 'X-Chorus-Client-Secret: 8899c64746474Cf18849c6B721b5Db51' -H 'X-Transaction-Id: ca5ef871-9b3f-4af4-958d-ee9c51094e08' -H 'Origin: https://www.chorus.co.nz'
|
||||
|
||||
// Build HTTP request
|
||||
client := http.Client{}
|
||||
req, err := http.NewRequest("GET", lookupURL, nil)
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
return "UNK"
|
||||
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")
|
||||
req.Header.Set("User-Agent", "https://tinker.nz/idanoo/flat-finder")
|
||||
|
||||
// Do the request
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
return "UNK"
|
||||
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 {
|
||||
log.Print(err)
|
||||
return "UNK"
|
||||
return "", err
|
||||
}
|
||||
|
||||
log.Println(string(bodyBytes))
|
||||
return "N/A"
|
||||
} else {
|
||||
log.Print("Invalid response from API: " + resp.Status)
|
||||
// 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 "UNK"
|
||||
return "", errors.New("Invalid response from API: " + resp.Status)
|
||||
}
|
||||
|
||||
// getAvailableSpeeds - Checks if VDSL/FIBRE is available
|
||||
func getAvailableSpeeds(address string) string {
|
||||
return chorusAddressLookup(address)
|
||||
// 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", chorusURL, nil)
|
||||
// if err != nil {
|
||||
// log.Print(err)
|
||||
// return "UNK"
|
||||
// }
|
||||
// Build HTTP request
|
||||
client := http.Client{}
|
||||
req, err := http.NewRequest("GET", lookupURL, nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// req.Header.Set("Content-TypeContent-Type", "application/json")
|
||||
// req.Header.Set("User-Agent", "https://tinker.nz/idanoo/flat-finder")
|
||||
// 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 {
|
||||
// log.Print(err)
|
||||
// return "UNK"
|
||||
// }
|
||||
// defer resp.Body.Close()
|
||||
// Do the request
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// if resp.StatusCode == http.StatusOK {
|
||||
// bodyBytes, err := io.ReadAll(resp.Body)
|
||||
// if err != nil {
|
||||
// log.Print(err)
|
||||
// return "UNK"
|
||||
// }
|
||||
// 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
|
||||
}
|
||||
|
||||
// log.Println(string(bodyBytes))
|
||||
// Decode JSON
|
||||
var chorusResult ChorusUniqueIdResponse
|
||||
err = json.Unmarshal(bodyBytes, &chorusResult)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// return "N/A"
|
||||
// } else {
|
||||
// log.Print("Invalid response from API: " + resp.Status)
|
||||
// }
|
||||
return int64(chorusResult.References.Tlc), nil
|
||||
}
|
||||
|
||||
return "UNK"
|
||||
return 0, errors.New("Invalid response from API: " + resp.Status)
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ func (c *LocalConfig) initDiscord() {
|
||||
func (c *LocalConfig) sendEmbeddedMessage(listing TradeMeListing) {
|
||||
log.Printf("New listing: %s", listing.Title)
|
||||
|
||||
hasFibre := getAvailableSpeeds(
|
||||
hasFibre, currentConn := getAvailableSpeeds(
|
||||
fmt.Sprintf(
|
||||
"%s, %s, %s",
|
||||
strings.TrimSpace(listing.Address),
|
||||
@ -62,7 +62,8 @@ func (c *LocalConfig) sendEmbeddedMessage(listing TradeMeListing) {
|
||||
true,
|
||||
).
|
||||
AddField("Bedrooms", fmt.Sprintf("%d", listing.Bedrooms), true).
|
||||
AddField("Has Fibre", hasFibre, true)
|
||||
AddField("Fibre Avail", hasFibre, false).
|
||||
AddField("Current Connection", currentConn, false)
|
||||
|
||||
// Only add address if token set
|
||||
if c.GoogleApiToken != "" && c.GoogleLocation1 != "" {
|
||||
|
@ -34,10 +34,11 @@ func (c *LocalConfig) loadConfig() {
|
||||
// Load it into global
|
||||
err = json.Unmarshal(data, c)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
maps := make(map[int64]bool)
|
||||
c.PostedProperties = maps
|
||||
} else {
|
||||
log.Printf("Loaded %d previously posted property IDs", len(c.PostedProperties))
|
||||
}
|
||||
|
||||
log.Printf("Loaded %d previously posted property IDs", len(c.PostedProperties))
|
||||
} else {
|
||||
// Create empty map for first run
|
||||
maps := make(map[int64]bool)
|
||||
|
Loading…
Reference in New Issue
Block a user