From ef7ca9f16ece281a8df2489d59703a868b0e5f29 Mon Sep 17 00:00:00 2001 From: Xevion Date: Tue, 26 Dec 2023 16:58:04 -0600 Subject: [PATCH] separate main code into different files (unsub, helpers) --- directory.go | 14 +++-- helpers.go | 52 +++++++++++++++++++ main.go | 144 --------------------------------------------------- unsub.go | 106 +++++++++++++++++++++++++++++++++++++ 4 files changed, 168 insertions(+), 148 deletions(-) create mode 100644 helpers.go create mode 100644 unsub.go diff --git a/directory.go b/directory.go index 63657a6..a27c17c 100644 --- a/directory.go +++ b/directory.go @@ -22,6 +22,9 @@ func Login(username string, password string) { // Send request response, err := DoRequestNoRead(request) + if err != nil { + log.Fatal().Err(err).Msg("Error sending login page request") + } doc, err := goquery.NewDocumentFromReader(response.Body) defer response.Body.Close() if err != nil { @@ -39,21 +42,24 @@ func Login(username string, password string) { "__RequestVerificationToken": {token}, "log-me-in": {"Log+In"}, } - log.Debug().Str("form", form.Encode()).Msg("Form Data") request, _ = http.NewRequest("POST", "https://www.utsa.edu/directory/", strings.NewReader(form.Encode())) ApplyHeaders(request) request.Header.Set("Content-Type", "application/x-www-form-urlencoded") // Send the login request - response, body, err := DoRequest(request) + response, _, err = DoRequest(request) if err != nil { log.Fatal().Err(err).Msg("Error sending login request") } if response.StatusCode != 200 { - log.Printf("%+v", string(body)) - log.Fatal().Str("status", response.Status).Msg("Error logging in") + switch response.StatusCode { + case 500: + log.Fatal().Str("status", response.Status).Msg("Bad Request (check cookies)") + default: + log.Fatal().Str("status", response.Status).Msg("Failed to Login, Unknown Error") + } } // TODO: Check if login was successful diff --git a/helpers.go b/helpers.go new file mode 100644 index 0000000..e2622f0 --- /dev/null +++ b/helpers.go @@ -0,0 +1,52 @@ +package main + +import ( + "io" + "net/http" + + "github.com/rs/zerolog/log" +) + +func DoRequestNoRead(req *http.Request) (*http.Response, error) { + log.Debug().Str("method", req.Method).Str("host", req.Host).Str("path", req.URL.Path).Msg("Request") + resp, err := client.Do(req) + + if err != nil { + log.Error().Err(err).Msg("Error making request") + return nil, err + } + + log.Debug().Int("code", resp.StatusCode).Str("content-type", resp.Header.Get("Content-Type")).Str("content-length", resp.Header.Get("Content-Length")).Msg("Response") + + return resp, nil +} + +func DoRequest(req *http.Request) (*http.Response, []byte, error) { + log.Debug().Str("method", req.Method).Str("host", req.Host).Str("path", req.URL.Path).Msg("Request") + resp, err := client.Do(req) + + if err != nil { + log.Error().Err(err).Msg("Error making request") + return nil, nil, err + } + + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + if err != nil { + log.Error().Err(err).Msg("Error reading response body") + return nil, nil, err + } + + log.Debug().Int("code", resp.StatusCode).Str("content-type", resp.Header.Get("Content-Type")).Int("content-length", len(body)).Msg("Response") + + return resp, body, nil +} + +func ApplyHeaders(req *http.Request) { + req.Header.Set("Origin", "http://www2.thescla.org") + req.Header.Set("Connection", "keep-alive") + req.Header.Set("User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:122.0) Gecko/20100101 Firefox/122.0") + req.Header.Set("Accept", "application/json, text/javascript, */*; q=0.01") + req.Header.Set("Accept-Language", "en-US,en;q=0.5") + req.Header.Set("Accept-Encoding", "gzip, deflate") +} diff --git a/main.go b/main.go index 93091bc..c84c43a 100644 --- a/main.go +++ b/main.go @@ -1,21 +1,14 @@ package main import ( - "crypto/sha256" - "encoding/json" - "fmt" - "io" "net/http" "net/http/cookiejar" - "net/url" "os" "os/signal" - "strings" "github.com/joho/godotenv" "github.com/rs/zerolog" "github.com/rs/zerolog/log" - "github.com/samber/lo" ) var client *http.Client @@ -29,143 +22,6 @@ func init() { } } -func DoRequestNoRead(req *http.Request) (*http.Response, error) { - log.Debug().Str("method", req.Method).Str("host", req.Host).Str("path", req.URL.Path).Msg("Request") - resp, err := client.Do(req) - - if err != nil { - log.Error().Err(err).Msg("Error making request") - return nil, err - } - - log.Debug().Int("code", resp.StatusCode).Str("content-type", resp.Header.Get("Content-Type")).Str("content-length", resp.Header.Get("Content-Length")).Msg("Response") - - return resp, nil -} - -func DoRequest(req *http.Request) (*http.Response, []byte, error) { - log.Debug().Str("method", req.Method).Str("host", req.Host).Str("path", req.URL.Path).Msg("Request") - resp, err := client.Do(req) - - if err != nil { - log.Error().Err(err).Msg("Error making request") - return nil, nil, err - } - - defer resp.Body.Close() - body, err := io.ReadAll(resp.Body) - if err != nil { - log.Error().Err(err).Msg("Error reading response body") - return nil, nil, err - } - - log.Debug().Int("code", resp.StatusCode).Str("content-type", resp.Header.Get("Content-Type")).Int("content-length", len(body)).Msg("Response") - - return resp, body, nil -} - -func ApplyHeaders(req *http.Request) { - req.Header.Set("Origin", "http://www2.thescla.org") - req.Header.Set("Connection", "keep-alive") - req.Header.Set("User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:122.0) Gecko/20100101 Firefox/122.0") - req.Header.Set("Accept", "application/json, text/javascript, */*; q=0.01") - req.Header.Set("Accept-Language", "en-US,en;q=0.5") - req.Header.Set("Accept-Encoding", "gzip, deflate") -} - -func Unsubscribe(email string) (*ConfirmationResponse, error) { - mktTok := "ODM5LU1PTC01NTIAAAGQRiDbOUWzUhLliVDxTHjxLfZDD1y0MxC47Wf_1C9UTbwEej3Tckhn_QteZR7p5Mpl3_f0ioPUyQ8XUceJ9a0PiOUJb_O3YIj8PwKNQEm4SseaSw" - - // Build referrer URL - referrerUrl, _ := url.Parse("http://www2.thescla.org/UnsubscribePage.html") - query := referrerUrl.Query() - query.Add("mkt_unsubscribe", "1") - query.Add("mkt_tok", mktTok) - referrerUrl.RawQuery = query.Encode() - - // Build lpUrl - thing := "839-MOL-552" - lpUrl := fmt.Sprintf("http://%s.mktoweb.com/lp/%s/UnsubscribePage.html?cr={creative}&kw={keyword}", thing, thing) - - values := url.Values{ - "Email": {email}, - "Unsubscribed": {"Yes"}, - "formid": {"1"}, - "lpId": {"1"}, - "subId": {"98"}, - "munchkinId": {thing}, - "lpurl": {lpUrl}, - "followupLpId": {"2"}, - "cr": {""}, - "kw": {""}, - "q": {""}, - "_mkt_trk": {""}, - "formVid": {"1"}, - "mkt_tok": {mktTok}, - "_mktoReferrer": {referrerUrl.String()}, - } - - // Grab checksum fields - fields := make([]string, 0, len(values)) - for key, _ := range values { - fields = append(fields, key) - } - values.Set("checksumFields", strings.Join(fields, ",")) - - // Calculate checksum - checksum := sha256.Sum256([]byte(strings.Join( - lo.Map(fields, func(field string, _ int) string { - return values.Get(field) - }), "|"))) - - values.Set("checksum", fmt.Sprintf("%x", checksum)) - - // Make request - request, _ := http.NewRequest("POST", "http://www2.thescla.org/index.php/leadCapture/save2", strings.NewReader(values.Encode())) - request.Header.Set("Referer", "http://www2.thescla.org/UnsubscribePage.html?mkt_unsubscribe=1") - request.Header.Set("Content-Type", "application/x-www-form-urlencoded") - request.Header.Set("X-Requested-With", "XMLHttpRequest") - ApplyHeaders(request) - - // Send request - response, body, err := DoRequest(request) - if err != nil { - panic(err) - } - - if response.StatusCode != 200 { - // If JSON returned, parse the message for the error - contentType := response.Header.Get("Content-Type") - if !strings.Contains(contentType, "application/json") { - return nil, UnsubscribeUnexpectedError{Message: string(body), Code: response.StatusCode} - } - - // Parse the JSON - var errorResponse ErrorResponse - err := json.Unmarshal(body, &errorResponse) - if err != nil { - log.Error().Err(err).Msg("Error parsing error response") - return nil, UnsubscribeUnexpectedError{Message: string(body), Code: response.StatusCode} - } - - switch errorResponse.Message { - case "checksum invalid": - return nil, ChecksumInvalidError(checksum) - case "checksum missing": - return nil, ChecksumMissingError(checksum) - case "Rejected": - return nil, UnsubscribeRejectedError(errorResponse.Message) - } - - log.Error().Str("content-type", contentType).Str("body", string(body)).Msg("Unknown Error") - return nil, UnsubscribeUnexpectedError{Message: string(body), Code: response.StatusCode} - } - - var confirmation ConfirmationResponse - json.Unmarshal(body, &confirmation) - return &confirmation, nil -} - func main() { stop := make(chan os.Signal, 1) signal.Notify(stop, os.Interrupt) diff --git a/unsub.go b/unsub.go new file mode 100644 index 0000000..9b3c957 --- /dev/null +++ b/unsub.go @@ -0,0 +1,106 @@ +package main + +import ( + "crypto/sha256" + "encoding/json" + "fmt" + "net/http" + "net/url" + "strings" + + "github.com/rs/zerolog/log" + "github.com/samber/lo" +) + +func Unsubscribe(email string) (*ConfirmationResponse, error) { + mktTok := "ODM5LU1PTC01NTIAAAGQRiDbOUWzUhLliVDxTHjxLfZDD1y0MxC47Wf_1C9UTbwEej3Tckhn_QteZR7p5Mpl3_f0ioPUyQ8XUceJ9a0PiOUJb_O3YIj8PwKNQEm4SseaSw" + + // Build referrer URL + referrerUrl, _ := url.Parse("http://www2.thescla.org/UnsubscribePage.html") + query := referrerUrl.Query() + query.Add("mkt_unsubscribe", "1") + query.Add("mkt_tok", mktTok) + referrerUrl.RawQuery = query.Encode() + + // Build lpUrl + thing := "839-MOL-552" + lpUrl := fmt.Sprintf("http://%s.mktoweb.com/lp/%s/UnsubscribePage.html?cr={creative}&kw={keyword}", thing, thing) + + values := url.Values{ + "Email": {email}, + "Unsubscribed": {"Yes"}, + "formid": {"1"}, + "lpId": {"1"}, + "subId": {"98"}, + "munchkinId": {thing}, + "lpurl": {lpUrl}, + "followupLpId": {"2"}, + "cr": {""}, + "kw": {""}, + "q": {""}, + "_mkt_trk": {""}, + "formVid": {"1"}, + "mkt_tok": {mktTok}, + "_mktoReferrer": {referrerUrl.String()}, + } + + // Grab checksum fields + fields := make([]string, 0, len(values)) + for key, _ := range values { + fields = append(fields, key) + } + values.Set("checksumFields", strings.Join(fields, ",")) + + // Calculate checksum + checksum := sha256.Sum256([]byte(strings.Join( + lo.Map(fields, func(field string, _ int) string { + return values.Get(field) + }), "|"))) + + values.Set("checksum", fmt.Sprintf("%x", checksum)) + + // Make request + request, _ := http.NewRequest("POST", "http://www2.thescla.org/index.php/leadCapture/save2", strings.NewReader(values.Encode())) + request.Header.Set("Referer", "http://www2.thescla.org/UnsubscribePage.html?mkt_unsubscribe=1") + request.Header.Set("Content-Type", "application/x-www-form-urlencoded") + request.Header.Set("X-Requested-With", "XMLHttpRequest") + ApplyHeaders(request) + + // Send request + response, body, err := DoRequest(request) + if err != nil { + panic(err) + } + + if response.StatusCode != 200 { + // If JSON returned, parse the message for the error + contentType := response.Header.Get("Content-Type") + if !strings.Contains(contentType, "application/json") { + return nil, UnsubscribeUnexpectedError{Message: string(body), Code: response.StatusCode} + } + + // Parse the JSON + var errorResponse ErrorResponse + err := json.Unmarshal(body, &errorResponse) + if err != nil { + log.Error().Err(err).Msg("Error parsing error response") + return nil, UnsubscribeUnexpectedError{Message: string(body), Code: response.StatusCode} + } + + switch errorResponse.Message { + case "checksum invalid": + return nil, ChecksumInvalidError(checksum) + case "checksum missing": + return nil, ChecksumMissingError(checksum) + case "Rejected": + return nil, UnsubscribeRejectedError(errorResponse.Message) + } + + log.Error().Str("content-type", contentType).Str("body", string(body)).Msg("Unknown Error") + return nil, UnsubscribeUnexpectedError{Message: string(body), Code: response.StatusCode} + } + + var confirmation ConfirmationResponse + json.Unmarshal(body, &confirmation) + return &confirmation, nil +}