-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add parameters and restructure code
- Loading branch information
1 parent
7100ab8
commit b45f2c8
Showing
27 changed files
with
567 additions
and
363 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package v2 | ||
|
||
import ( | ||
"regexp" | ||
) | ||
|
||
var ( | ||
RegexProduct = regexp.MustCompile(`pr([1-9]|[1-9][0-9]|1[0-9]{2}|200)`) | ||
) | ||
|
||
const ( | ||
ParameterItem = "pr" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
package v2 | ||
|
||
type Data map[string]any |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
package v2 | ||
|
||
import ( | ||
"net/url" | ||
"regexp" | ||
"strings" | ||
|
||
"github.com/mitchellh/mapstructure" | ||
"github.com/pkg/errors" | ||
) | ||
|
||
func Decode(input url.Values, output interface{}) error { | ||
data := Data{} | ||
|
||
// decode values | ||
for k, v := range input { | ||
// handle maps | ||
if ok, err := DecodeMapValue(k, v, data); err != nil { | ||
return err | ||
} else if ok { | ||
continue | ||
} | ||
|
||
// handle slices | ||
if ok, err := DecodeRegexValue(k, v, RegexProduct, data, ParameterItem); err != nil { | ||
return err | ||
} else if ok { | ||
continue | ||
} | ||
|
||
// default | ||
v, err := url.QueryUnescape(v[0]) | ||
if err != nil { | ||
return err | ||
} | ||
data[k] = v | ||
} | ||
|
||
if err := mapstructure.WeakDecode(data, output); err != nil { | ||
return errors.Wrap(err, "failed to weakly decode query") | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func DecodeMapValue(k string, v []string, data Data) (bool, error) { | ||
if strings.Contains(k, ".") { | ||
parts := strings.Split(k, ".") | ||
if _, ok := data[parts[0]]; !ok { | ||
data[parts[0]] = map[string]any{} | ||
} | ||
if value, ok := data[parts[0]].(map[string]any); ok { | ||
v, err := url.QueryUnescape(v[0]) | ||
if err != nil { | ||
return false, err | ||
} | ||
value[strings.Join(parts[1:], ".")] = v | ||
} | ||
return true, nil | ||
} | ||
return false, nil | ||
} | ||
|
||
// DecodeRegexValue e.g. `pr1=idSKU_123456` = map["pr"][]map["id"]="SKU_123456" | ||
func DecodeRegexValue(k string, v []string, r *regexp.Regexp, data Data, key string) (bool, error) { | ||
if r.MatchString(k) { | ||
value, err := DecodeObjectValue(v[0]) | ||
if err != nil { | ||
return false, err | ||
} | ||
if value != nil { | ||
v, ok := data[key].([]map[string]any) | ||
if !ok { | ||
v = []map[string]any{} | ||
} | ||
v = append(v, value) | ||
data[key] = v | ||
return true, nil | ||
} | ||
} | ||
return false, nil | ||
} | ||
|
||
// DecodeObjectValue e.g. `idSKU_123456` = map["id"]="SKU_123456" | ||
func DecodeObjectValue(s string) (map[string]any, error) { | ||
if len(s) == 0 { | ||
return nil, nil //nolint:nilnil | ||
} | ||
ret := map[string]any{} | ||
for _, part := range strings.Split(s, "~") { | ||
v, err := url.QueryUnescape(part[2:]) | ||
if err != nil { | ||
return nil, err | ||
} | ||
ret[part[0:2]] = v | ||
} | ||
return ret, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
package v2 | ||
|
||
import ( | ||
"bytes" | ||
"encoding/json" | ||
"fmt" | ||
"io" | ||
"net/url" | ||
"sort" | ||
"strings" | ||
|
||
"github.com/pkg/errors" | ||
) | ||
|
||
func Encode(input *Event) (url.Values, io.Reader, error) { | ||
var richsstsse bool | ||
// NOTE: `richsstsse` seems to be last parameter in the query to let's ensure it stays that way | ||
if input.Richsstsse != nil { | ||
richsstsse = true | ||
input.Richsstsse = nil | ||
} | ||
|
||
a, err := json.Marshal(input) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
|
||
data := Data{} | ||
if err := json.Unmarshal(a, &data); err != nil { | ||
return nil, nil, errors.Wrap(err, "failed to decode into map") | ||
} | ||
|
||
ret := url.Values{} | ||
for k, v := range data { | ||
switch t := v.(type) { | ||
case []interface{}: | ||
for key, value := range t { | ||
switch tt := value.(type) { | ||
case map[string]interface{}: | ||
ret[fmt.Sprintf("%s%d", k, key+1)] = []string{EncodeObjectValue(tt)} | ||
default: | ||
panic("unhandled") | ||
} | ||
} | ||
case map[string]string: | ||
for key, value := range t { | ||
ret[fmt.Sprintf("%s.%s", k, key)] = []string{value} | ||
} | ||
case map[string]interface{}: | ||
for key, value := range t { | ||
ret[fmt.Sprintf("%s.%s", k, key)] = []string{fmt.Sprintf("%v", value)} | ||
} | ||
case *string: | ||
ret[k] = []string{*t} | ||
case string: | ||
ret[k] = []string{t} | ||
default: | ||
panic("unhandled") | ||
} | ||
} | ||
|
||
var body []string | ||
var reader io.Reader | ||
maxQueryLength := 2048 // | ||
if richsstsse { | ||
maxQueryLength -= len("&richsstsse") | ||
} | ||
for len(ret.Encode()) > maxQueryLength { | ||
for s, i := range ret { | ||
ret.Del(s) | ||
body = append(body, s+"="+i[0]) | ||
break | ||
} | ||
} | ||
|
||
if richsstsse { | ||
ret.Add("richsstsse", "") | ||
} | ||
|
||
if len(body) > 0 { | ||
reader = bytes.NewReader([]byte(strings.Join(body, "&"))) | ||
} | ||
|
||
return ret, reader, nil | ||
} | ||
|
||
// EncodeObjectValue e.g. `idSKU_123456` = map["id"]="SKU_123456" | ||
func EncodeObjectValue(s map[string]any) string { | ||
if len(s) == 0 { | ||
return "" | ||
} | ||
keys := make([]string, 0, len(s)) | ||
for k := range s { | ||
keys = append(keys, k) | ||
} | ||
sort.Strings(keys) | ||
ret := make([]string, 0, len(keys)) | ||
for _, k := range keys { | ||
ret = append(ret, k+fmt.Sprintf("%s", s[k])) | ||
} | ||
return strings.Join(ret, "~") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package v2_test | ||
|
||
import ( | ||
"net/url" | ||
"testing" | ||
|
||
mpv2 "github.com/foomo/sesamy-go/measurementprotocol/v2" | ||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestEncode(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
args string | ||
want error | ||
}{ | ||
{ | ||
name: "page_view", | ||
args: "v=2&tid=G-123456>m=45je42s0v893689383z8894072534za200&_p=1709286636310&gcd=13l3l3l3l1&npa=0&dma_cps=sypham&dma=1&cid=292234677.1707898933&ul=en-us&sr=3840x1600&uaa=arm&uab=64&uafvl=Chromium&uamb=0&uam=&uap=macOS&uapv=14.3.1&uaw=0&are=1&pae=1&pscdl=noapi&_s=1&sid=1709286452&sct=7&seg=1&dl=https%3A%2F%2Fwww.homemade.ch%2Fprodukt%2Fkuhn-rikon-wiegemesser-900047100%3Fid%3D900047100&dr=https%3A%2F%2Fwww.homemade.ch%2Fmesser-besteck&dt=Wiegemesser&en=page_view&tfd=5682", | ||
want: nil, | ||
}, | ||
// { | ||
// name: "add_to_cart", | ||
// args: "v=2&tid=G-123456>m=45je42s0v9175354889z89175348963za200&_p=1709297934217&_dbg=1&gcd=13l3l3l3l1&npa=0&dma_cps=sypham&dma=1&cid=1220643501.1708014725&ul=en-us&sr=3840x1600&_fplc=0&ur=DE-BY&uaa=arm&uab=64&uafvl=Chromium&uamb=0&uam=&uap=macOS&uapv=14.3.1&uaw=0&are=1&pscdl=noapi&_eu=IA&sst.uc=DE&sst.etld=google.de&sst.gcsub=region1&sst.gcd=13l3l3l3l1&sst.tft=1709297934217&_s=8&cu=USD&sid=1709296380&sct=7&seg=1&dl=https%3A%2F%2Fsniffer.cloud.bestbytes.net%2F%3Fgtm_debug%3D1709297933868&dr=https%3A%2F%2Ftagassistant.google.com%2F&dt=Server%20Side%20Tracking%20Prototype%20(codename%3A%20sniffer)&en=add_to_cart&pr1=idSKU_12345~nmStan%20and%20Friends%20Tee~afGoogle%20Store~cpSUMMER_FUN~ds2.22~lp5~brGoogle~caApparel~c2Adult~c3Shirts~c4Crew~c5Short%20sleeve~lirelated_products~lnRelated%20products~vagreen~loChIJIQBpAG2ahYAR_6128GcTUEo~pr10.01~qt3&epn.value=30.03&tfd=15129&richsstsse", | ||
// want: nil, | ||
// }, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
u, err := url.ParseQuery(tt.args) | ||
require.NoError(t, err) | ||
e := &mpv2.Event{} | ||
require.NoError(t, mpv2.Decode(u, e)) | ||
if !assert.Empty(t, e.Unknown) { | ||
t.Errorf("Encode() = %v, want %v", e.Unknown, nil) | ||
} | ||
if out, _, err := mpv2.Encode(e); assert.NoError(t, err) { | ||
assert.EqualValues(t, u, out) | ||
} | ||
}) | ||
} | ||
} |
Oops, something went wrong.