diff --git a/broker/broker.go b/broker/broker.go index 1c0ab52..1568305 100644 --- a/broker/broker.go +++ b/broker/broker.go @@ -3,12 +3,10 @@ package broker import ( "context" "encoding/json" - "errors" "local/storage" "local/truckstop/config" "local/truckstop/logtr" "net/http" - "net/http/cookiejar" "strings" "time" @@ -37,41 +35,64 @@ func _do(db storage.DB, r *http.Request) (*http.Response, error) { client := &http.Client{ Timeout: time.Hour, } - newjar, err := cookiejar.New(&cookiejar.Options{}) - if err != nil { - return nil, errors.New("failed to make a cookie jar: " + err.Error()) - } - client.Jar = newjar cookieJarKey := "cookies_" + r.URL.Host cookies, err := getCookies(db, cookieJarKey) if err != nil { - logtr.Errorf("failed to load cookies: %v", err) + logtr.Errorf("failed to get cookies: %v", err) } else { - client.Jar.SetCookies(r.URL, cookies) + logtr.Verbosef("got cookies for %s: %+v", cookieJarKey, cookies) + for _, cookie := range cookies { + r.Header.Add("Cookie", cookie) + } } + logtr.Verbosef("_do: %+v", r) resp, err := client.Do(r) if err != nil { return nil, err } - if err := setCookies(db, cookieJarKey, client.Jar.Cookies(r.URL)); err != nil { + if err := setCookies(db, cookieJarKey, resp); err != nil { logtr.Errorf("failed to set cookies: %v", err) } return resp, err } -func getCookies(db storage.DB, host string) ([]*http.Cookie, error) { +func getCookies(db storage.DB, host string) ([]string, error) { b, err := db.Get(host) if err != nil { return nil, err } - var result []*http.Cookie + var result []string err = json.Unmarshal(b, &result) return result, err } -func setCookies(db storage.DB, host string, cookies []*http.Cookie) error { - b, err := json.Marshal(cookies) +func setCookies(db storage.DB, host string, resp *http.Response) error { + nameValues := [][2]string{} + old, _ := getCookies(db, host) + for _, value := range old { + name := strings.Split(value, "=")[0] + nameValues = append(nameValues, [2]string{name, value}) + } + for _, value := range resp.Header["Set-Cookie"] { + name := strings.Split(value, "=")[0] + found := false + for i := range nameValues { + if nameValues[i][0] == name { + found = true + nameValues[i][1] = value + } + } + if !found { + nameValues = append(nameValues, [2]string{name, value}) + } + } + result := []string{} + for i := range nameValues { + result = append(result, nameValues[i][1]) + } + logtr.Verbosef("setting cookies for %s: %+v", host, result) + b, err := json.Marshal(result) if err != nil { return err } diff --git a/broker/broker_test.go b/broker/broker_test.go index 9ef8085..cb88453 100644 --- a/broker/broker_test.go +++ b/broker/broker_test.go @@ -5,6 +5,7 @@ import ( "local/storage" "net/http" "net/http/httptest" + "strconv" "strings" "testing" "time" @@ -12,24 +13,33 @@ import ( "golang.org/x/time/rate" ) +func TestBrokerInterface(t *testing.T) { + var b Broker + b = NTGVision{} + _ = b +} + func TestDoCookies(t *testing.T) { limiter = rate.NewLimiter(rate.Limit(20.0), 1) calls := 0 db := storage.NewMap() s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { calls += 1 - if calls == 1 { - http.SetCookie(w, &http.Cookie{ - Name: "name", - Value: "value", - Expires: time.Now().Add(time.Hour), - }) - } else { - if !strings.Contains(fmt.Sprint(r.Header["Cookie"]), "name=value") { + if calls != 1 { + if !strings.Contains(fmt.Sprint(r.Header["Cookie"]), "name=value"+strconv.Itoa(calls-1)) { w.WriteHeader(http.StatusBadRequest) - t.Error("cookie not set on calls after first") + t.Error("cookie not set as latest") + } + if !strings.Contains(fmt.Sprint(r.Header["Cookie"]), "Expires") { + w.WriteHeader(http.StatusBadRequest) + t.Error("cookie not expiration: ", r.Header["Cookie"]) } } + http.SetCookie(w, &http.Cookie{ + Name: "name", + Value: "value" + strconv.Itoa(calls), + Expires: time.Now().Add(time.Hour), + }) })) defer s.Close() req, _ := http.NewRequest(http.MethodGet, s.URL, nil) diff --git a/broker/ntgvision.go b/broker/ntgvision.go index 3abbde8..89912d3 100644 --- a/broker/ntgvision.go +++ b/broker/ntgvision.go @@ -335,6 +335,7 @@ func (ntg NTGVision) newRequest(states []config.State) (*http.Request, error) { } setNTGHeaders(request) request.Header.Set("Authorization", "Bearer "+getNTGToken()) + request.Header.Set("Cookie", "NTGAuthToken="+getNTGToken()) return request, nil } diff --git a/config.json b/config.json index b39b138..c9c7a50 100644 --- a/config.json +++ b/config.json @@ -77,7 +77,7 @@ "LoadPageURIFormat": "https://ntgvision.com/LoadDetails?loadId=%d", "LoadPageAPIURIFormat": "https://ntgvision.com/api/v1/load/LoadDetails?loadId==%d", "Username": "noeasyrunstrucking@gmail.com", - "Password": "thumper1234" + "Password": "thumper12345" } } } diff --git a/config.main_test.json b/config.main_test.json new file mode 100644 index 0000000..c9e3335 --- /dev/null +++ b/config.main_test.json @@ -0,0 +1,83 @@ +{ + "Log": { + "Path": "/tmp/truckstop.log", + "Level": "sos", + "SOSMatrix": { + "ReceiveEnabled": true, + "Mock": true, + "Homeserver": "https://m.bltrucks.top", + "Username": "@bot.m.bltrucks.top", + "Token": "mvDWB96KXMF8XhOam8EC5XVdQvSEw0CDeClcSWocBcYkwZX3FPNWZ5uOnQk2EmT1cjpzfeuD7gDYPPjOuyZlI3bE9TE35UjNOlZgi0Tugm25s91iVsbIF6kMZsCIhVMSmEf6w3jxX6wQYOWvmDZ4mu6f5c8wr221EMDcOpEzQV09d1zuBSWgKLBgjqAkYHJZ5dTRIWpEDpPgujhOFZa2ld1HiAOxrJKlIrlfDBN0CUsTlGOGplujDAr4VtpFzNRS", + "Device": "TGNIOGKATZ", + "Room": "!OYZqtInrBCn1cyz90D:m.bltrucks.top" + } + }, + "Interval": { + "Input": "5s..10s", + "OK": "6h0m0s..6h0m0s", + "Error": "6h0m0s..6h0m0s", + "JobInfo": "10s..20s" + }, + "Images": { + "ClientID": "d9ac7cabe813d10", + "ClientSecret": "9d0b3d82800b30ca88f595d3bcd6985f627d7d82", + "RefreshToken": "171417741bf762b99b0b9f9137491b7a69874a77", + "AccessToken": "e63db98f92d2db7ac7f56914a2030c889b378e9b", + "RefreshURI": "https://api.imgur.com/oauth2/token", + "RefreshFormat": "refresh_token=%s\u0026client_id=%s\u0026client_secret=%s\u0026grant_type=refresh_token", + "RefreshMethod": "POST", + "UploadURI": "https://api.imgur.com/3/image?name=something.jpeg", + "UploadMethod": "POST" + }, + "Maps": { + "URIFormat": "https://maps.googleapis.com/maps/api/staticmap?center=%s\u0026markers=label=A|%s\u0026zoom=5\u0026size=250x250\u0026scale=1\u0026format=jpeg\u0026maptype=roadmap\u0026key=AIzaSyBkACm-LQkoSfsTO5_XAzBVZE9-JQzcNkg", + "Pickup": false, + "Dropoff": false, + "Pathed": { + "Enabled": true, + "DirectionsURIFormat": "https://maps.googleapis.com/maps/api/directions/json?origin=%s\u0026destination=%s\u0026mode=driving\u0026key=AIzaSyBkACm-LQkoSfsTO5_XAzBVZE9-JQzcNkg", + "PathedURIFormat": "https://maps.googleapis.com/maps/api/staticmap?size=250x250\u0026path=%s\u0026format=jpeg\u0026maptype=roadmap\u0026key=AIzaSyBkACm-LQkoSfsTO5_XAzBVZE9-JQzcNkg\u0026size=250x250\u0026markers=%s|%s", + "Zoom": { + "AcceptableLatLngDelta": 2, + "Override": 5 + } + } + }, + "Clients": { + "bel": { + "States": [ + "NC" + ], + "IDs": { + "Matrix": "@bel:m.bltrucks.top" + }, + "Available": 1512328400 + } + }, + "Storage": [ + "files", + "/tmp/play" + ], + "Message": { + "Matrix": { + "ReceiveEnabled": true, + "Mock": true, + "Homeserver": "https://m.bltrucks.top", + "Username": "@bot.m.bltrucks.top", + "Token": "mvDWB96KXMF8XhOam8EC5XVdQvSEw0CDeClcSWocBcYkwZX3FPNWZ5uOnQk2EmT1cjpzfeuD7gDYPPjOuyZlI3bE9TE35UjNOlZgi0Tugm25s91iVsbIF6kMZsCIhVMSmEf6w3jxX6wQYOWvmDZ4mu6f5c8wr221EMDcOpEzQV09d1zuBSWgKLBgjqAkYHJZ5dTRIWpEDpPgujhOFZa2ld1HiAOxrJKlIrlfDBN0CUsTlGOGplujDAr4VtpFzNRS", + "Device": "TGNIOGKATZ", + "Room": "!OYZqtInrBCn1cyz90D:m.bltrucks.top" + } + }, + "Once": true, + "Brokers": { + "NTG": { + "JobInfo": true, + "Mock": true, + "LoadPageURIFormat": "https://ntgvision.com/LoadDetails?loadId=%d", + "LoadPageAPIURIFormat": "https://ntgvision.com/api/v1/load/LoadDetails?loadId==%d", + "Username": "noeasyrunstrucking@gmail.com", + "Password": "thumper1234" + } + } +} diff --git a/config/config.go b/config/config.go index bbb89fc..6019fcb 100644 --- a/config/config.go +++ b/config/config.go @@ -72,6 +72,11 @@ type Config struct { Username string Password string } + FastExact struct { + Mock bool + Username string + Password string + } } lock sync.Mutex diff --git a/config/state.go b/config/state.go index 337d273..6ee474a 100644 --- a/config/state.go +++ b/config/state.go @@ -7,56 +7,56 @@ import ( type State string -var States = map[string]State{ - "99654": "AL", - "72401": "AR", - "85364": "AZ", - "90011": "CA", - "80013": "CO", - "06902": "CT", - "19720": "DE", - "33024": "FL", - "30043": "GA", - "96706": "HI", - "50613": "IA", - "83646": "ID", - "60629": "IL", - "47906": "IN", - "66062": "KS", - "40475": "KY", - "70726": "LA", - "02301": "MA", - "20906": "MD", - "04401": "ME", - "48197": "MI", - "55106": "MN", - "63376": "MO", - "39503": "MS", - "59901": "MT", - "27006": "NC", - "58103": "ND", - "68516": "NE", - "03103": "NH", - "08701": "NJ", - "87121": "NM", - "89108": "NV", - "11368": "NY", - "45011": "OH", - "73099": "OK", - "97006": "OR", - "19120": "PA", - "02860": "RI", - "29483": "SC", - "57106": "SD", - "37013": "TN", - "77449": "TX", - "84058": "UT", - "22193": "VA", - "05401": "VT", - "99301": "WA", - "53215": "WI", - "26554": "WV", - "82001": "WY", +var States = map[State]string{ + "AL": "99654", + "AR": "72401", + "AZ": "85364", + "CA": "90011", + "CO": "80013", + "CT": "06902", + "DE": "19720", + "FL": "33024", + "GA": "30043", + "HI": "96706", + "IA": "50613", + "ID": "83646", + "IL": "60629", + "IN": "47906", + "KS": "66062", + "KY": "40475", + "LA": "70726", + "MA": "02301", + "MD": "20906", + "ME": "04401", + "MI": "48197", + "MN": "55106", + "MO": "63376", + "MS": "39503", + "MT": "59901", + "NC": "27006", + "ND": "58103", + "NE": "68516", + "NH": "03103", + "NJ": "08701", + "NM": "87121", + "NV": "89108", + "NY": "11368", + "OH": "45011", + "OK": "73099", + "OR": "97006", + "PA": "19120", + "RI": "02860", + "SC": "29483", + "SD": "57106", + "TN": "37013", + "TX": "77449", + "UT": "84058", + "VA": "22193", + "VT": "05401", + "WA": "99301", + "WI": "53215", + "WV": "26554", + "WY": "82001", } func (state *State) UnmarshalJSON(b []byte) error { @@ -65,8 +65,8 @@ func (state *State) UnmarshalJSON(b []byte) error { return err } for k := range States { - if string(States[k]) == s { - *state = States[k] + if string(k) == s { + *state = k return nil } } diff --git a/main.go b/main.go index 048fcb5..66b5eb7 100644 --- a/main.go +++ b/main.go @@ -21,13 +21,19 @@ import ( var stateFinder = regexp.MustCompile(`[A-Za-z]+`) func main() { - if err := config.Refresh(message.NewSOSMatrix); err != nil { + if err := _main(); err != nil { panic(err) } +} + +func _main() error { + if err := config.Refresh(message.NewSOSMatrix); err != nil { + return err + } if config.Get().Message.Matrix.ReceiveEnabled { if err := matrixrecv(); err != nil { logtr.SOSf("failed to recv matrix on boot: %v", err) - panic(err) + return err } } lock := &sync.Mutex{} @@ -47,11 +53,12 @@ func main() { } } }() - if err := _main(); err != nil { - logtr.SOSf("failed _main: %v", err) - panic(err) + if err := __main(); err != nil { + logtr.SOSf("failed __main: %v", err) + return err } lock.Lock() + return nil } func matrixrecv() error { @@ -228,9 +235,9 @@ func parseOutStates(b []byte) []config.State { return states } -func _main() error { +func __main() error { for { - err := _mainOne() + err := __mainOne() if err != nil { logtr.Errorf("failed _main: %v", err) } @@ -247,7 +254,7 @@ func _main() error { return nil } -func _mainOne() error { +func __mainOne() error { logtr.Debugf("config.refreshing...") if err := config.Refresh(message.NewSOSMatrix); err != nil { logtr.SOSf("bad config: %v", err) @@ -258,7 +265,7 @@ func _mainOne() error { logtr.SOSf("failed once(): %v", err) return err } - logtr.Debugf("/_mainOne") + logtr.Debugf("/__mainOne") return nil } diff --git a/main_test.go b/main_test.go index 11dcf2d..9cd3381 100644 --- a/main_test.go +++ b/main_test.go @@ -3,6 +3,7 @@ package main import ( "fmt" "local/truckstop/config" + "os" "testing" ) @@ -33,3 +34,10 @@ Content-Type: text/html; charset="UTF-8" t.Fatal(want, got) } } + +func TestMain(t *testing.T) { + os.Setenv("CONFIG", "./config.main_test.json") + if err := _main(); err != nil { + t.Fatal(err) + } +}