mirror of
https://github.com/Xevion/scla-unsubscribe.git
synced 2025-12-06 05:16:26 -06:00
next iteration on unsubscribing
This commit is contained in:
9
go.mod
9
go.mod
@@ -1,3 +1,12 @@
|
|||||||
module unsubscribe
|
module unsubscribe
|
||||||
|
|
||||||
go 1.21.3
|
go 1.21.3
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||||
|
github.com/rs/zerolog v1.31.0 // indirect
|
||||||
|
github.com/samber/lo v1.39.0 // indirect
|
||||||
|
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect
|
||||||
|
golang.org/x/sys v0.12.0 // indirect
|
||||||
|
)
|
||||||
|
|||||||
19
go.sum
Normal file
19
go.sum
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||||
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
|
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||||
|
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||||
|
github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A=
|
||||||
|
github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
|
||||||
|
github.com/samber/lo v1.39.0 h1:4gTz1wUhNYLhFSKl6O+8peW0v2F4BCY034GRpU9WnuA=
|
||||||
|
github.com/samber/lo v1.39.0/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
|
||||||
|
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 h1:3MTrJm4PyNL9NBqvYDSj3DHl46qQakyfqfWo4jgfaEM=
|
||||||
|
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE=
|
||||||
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
|
||||||
|
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
31
logs.go
Normal file
31
logs.go
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog"
|
||||||
|
)
|
||||||
|
|
||||||
|
const timeFormat = "2006-01-02 15:04:05"
|
||||||
|
|
||||||
|
var (
|
||||||
|
standardOut = zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: timeFormat}
|
||||||
|
errorOut = zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: timeFormat}
|
||||||
|
)
|
||||||
|
|
||||||
|
// logSplitter implements zerolog.LevelWriter
|
||||||
|
type logSplitter struct{}
|
||||||
|
|
||||||
|
// Write should not be called
|
||||||
|
func (l logSplitter) Write(p []byte) (n int, err error) {
|
||||||
|
return os.Stdout.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteLevel write to the appropriate output
|
||||||
|
func (l logSplitter) WriteLevel(level zerolog.Level, p []byte) (n int, err error) {
|
||||||
|
if level <= zerolog.WarnLevel {
|
||||||
|
return standardOut.Write(p)
|
||||||
|
} else {
|
||||||
|
return errorOut.Write(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
140
main.go
140
main.go
@@ -1,11 +1,25 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
"github.com/samber/lo"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var client = &http.Client{}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
log.Logger = zerolog.New(logSplitter{}).With().Timestamp().Logger()
|
||||||
|
}
|
||||||
|
|
||||||
type Confirmation struct {
|
type Confirmation struct {
|
||||||
FormId string `json:"formId"`
|
FormId string `json:"formId"`
|
||||||
FollowUpUrl string `json:"followUpUrl"`
|
FollowUpUrl string `json:"followUpUrl"`
|
||||||
@@ -14,35 +28,113 @@ type Confirmation struct {
|
|||||||
AliId string `json:"aliId"`
|
AliId string `json:"aliId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func Unsubscribe() {
|
func DoRequest(req *http.Request) (*http.Response, []byte, error) {
|
||||||
values := url.Values{
|
log.Debug().Str("method", req.Method).Str("host", req.Host).Str("path", req.URL.Path).Msg("Request")
|
||||||
"Email": {"ryan.walters@my.utsa.edu"},
|
resp, err := client.Do(req)
|
||||||
"Unsubscribed": {"Yes"},
|
|
||||||
"formid": {"1"},
|
if err != nil {
|
||||||
"lpId": {"1"},
|
log.Error().Err(err).Msg("Error making request")
|
||||||
"subId": {"98"},
|
return nil, nil, err
|
||||||
"munchkinId": {"839-MOL-552"},
|
|
||||||
"lpurl": {"http://839-MOL-552.mktoweb.com/lp/839-MOL-552/UnsubscribePage.html?cr={creative}&kw={keyword}"},
|
|
||||||
"followupLpId": {"2"},
|
|
||||||
"cr": {""},
|
|
||||||
"kw": {""},
|
|
||||||
"q": {""},
|
|
||||||
"_mkt_trk": {""},
|
|
||||||
"formVid": {"1"},
|
|
||||||
"mkt_tok": {"ODM5LU1PTC01NTIAAAGQRiDbOUWzUhLliVDxTHjxLfZDD1y0MxC47Wf_1C9UTbwEej3Tckhn_QteZR7p5Mpl3_f0ioPUyQ8XUceJ9a0PiOUJb_O3YIj8PwKNQEm4SseaSw"},
|
|
||||||
"_mktoReferrer": {"http://www2.thescla.org/UnsubscribePage.html?mkt_unsubscribe=1&mkt_tok=ODM5LU1PTC01NTIAAAGQRiDbOUWzUhLliVDxTHjxLfZDD1y0MxC47Wf_1C9UTbwEej3Tckhn_QteZR7p5Mpl3_f0ioPUyQ8XUceJ9a0PiOUJb_O3YIj8PwKNQEm4SseaSw"},
|
|
||||||
"checksumFields": {"Email,Unsubscribed,formid,lpId,subId,munchkinId,lpurl,followupLpId,cr,kw,q,_mkt_trk,formVid,mkt_tok,_mktoReferrer"},
|
|
||||||
"checksum": {"062bb614ebe52a624577123e91c0e7e0d6d069178d2d23d7bd1fa9db85b05472"},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
req, _ := http.NewRequest("POST", "http://www2.thescla.org/index.php/leadCapture/save2", strings.NewReader(values.Encode()))
|
defer resp.Body.Close()
|
||||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
body, err := io.ReadAll(resp.Body)
|
||||||
req.Header.Set("X-Requested-With", "XMLHttpRequest")
|
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("Origin", "http://www2.thescla.org")
|
||||||
req.Header.Set("Connection", "keep-alive")
|
req.Header.Set("Connection", "keep-alive")
|
||||||
req.Header.Set("Referer", "http://www2.thescla.org/UnsubscribePage.html?mkt_unsubscr")
|
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) *Confirmation {
|
||||||
|
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()
|
||||||
|
|
||||||
|
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()},
|
||||||
|
}
|
||||||
|
|
||||||
|
fields := []string{"Email", "Unsubscribed", "formid", "lpId", "subId", "munchkinId", "lpurl", "followupLpId", "cr", "kw", "q", "_mkt_trk", "formVid", "mkt_tok", "_mktoReferrer"}
|
||||||
|
// fields := make([]string, 0, len(values))
|
||||||
|
// for key, _ := range values {
|
||||||
|
// fields = append(fields, key)
|
||||||
|
// }
|
||||||
|
values.Set("checksumFields", strings.Join(fields, ","))
|
||||||
|
log.Printf("%+v", values.Get("checksumFields"))
|
||||||
|
|
||||||
|
// Calculate checksum
|
||||||
|
h := sha256.New()
|
||||||
|
h.Write([]byte(strings.Join(
|
||||||
|
lo.Map(fields, func(field string, _ int) string {
|
||||||
|
return values.Get(field)
|
||||||
|
}), "|")))
|
||||||
|
|
||||||
|
hex := fmt.Sprintf("%x", h.Sum(nil))
|
||||||
|
values.Set("checksum", hex)
|
||||||
|
log.Debug().Str("hex", hex).Msg("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)
|
||||||
|
|
||||||
|
response, body, err := DoRequest(request)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if response.StatusCode != 200 {
|
||||||
|
log.Print(string(body))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var confirmation Confirmation
|
||||||
|
json.Unmarshal(body, &confirmation)
|
||||||
|
return &confirmation
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
conf := Unsubscribe("ryan.walters@my.utsa.edu")
|
||||||
|
if conf != nil {
|
||||||
|
log.Info().Str("formId", conf.FormId).Str("followUpUrl", conf.FollowUpUrl).Str("deliveryType", conf.DeliveryType).Str("followUpStreamValue", conf.FollowUpStreamValue).Str("aliId", conf.AliId).Msg("Unsubscribed")
|
||||||
|
} else {
|
||||||
|
log.Error().Msg("Failed to Unsubscribe")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user