Пример #1
0
// Split a string, accepts an optional with parameter
//
//     split(item, ",")
//
func SplitFunc(ctx expr.EvalContext, input value.Value, splitByV value.StringValue) (value.StringsValue, bool) {

	sv, ok := value.ToString(input.Rv())
	splitBy, splitByOk := value.ToString(splitByV.Rv())
	if !ok || !splitByOk {
		return value.NewStringsValue(make([]string, 0)), false
	}
	if sv == "" {
		return value.NewStringsValue(make([]string, 0)), false
	}
	if splitBy == "" {
		return value.NewStringsValue(make([]string, 0)), false
	}
	vals := strings.Split(sv, splitBy)
	return value.NewStringsValue(vals), true
}
Пример #2
0
func (m ContextUrlValues) Row() map[string]value.Value {
	mi := make(map[string]value.Value)
	for k, v := range m.Data {
		if len(v) == 1 {
			mi[k] = value.NewValue(v[0])
		} else if len(v) > 1 {
			mi[k] = value.NewStringsValue(v)
		}
	}
	return mi
}
Пример #3
0
// Extract Domains from a Value, or Values (must be urlish), doesn't do much/any validation
//
//     domains("http://www.lytics.io/index.html") =>  []string{"lytics.io"}
//
func DomainsFunc(ctx expr.EvalContext, items ...value.Value) (value.StringsValue, bool) {

	vals := value.NewStringsValue(make([]string, 0))
	for _, item := range items {
		switch itemT := item.(type) {
		case value.StringValue:
			vals.Append(itemT.Val())
		case value.StringsValue:
			for _, sv := range itemT.Val() {
				vals.Append(sv)
			}
		}
	}

	if vals.Len() == 0 {
		return vals, true
	}
	domains := value.NewStringsValue(make([]string, 0))
	for _, val := range vals.Val() {
		urlstr := strings.ToLower(val)
		if len(urlstr) < 8 {
			continue
		}
		if !strings.HasPrefix(urlstr, "http") {
			urlstr = "http://" + urlstr
		}
		if urlParsed, err := url.Parse(urlstr); err == nil {
			parts := strings.Split(urlParsed.Host, ".")
			if len(parts) > 2 {
				parts = parts[len(parts)-2:]
			}
			if len(parts) > 0 {
				domains.Append(strings.Join(parts, "."))
			}

		}
	}
	return domains, true
}
Пример #4
0
// Extract hosts from a Strings (must be urlish), doesn't do much/any validation
//
//     hosts("http://www.lytics.io", "http://www.activate.lytics.io") => www.lytics.io, www.activate.lytics.io
//
func HostsFunc(ctx expr.EvalContext, items ...value.Value) (value.StringsValue, bool) {
	vals := value.NewStringsValue(make([]string, 0))
	for _, item := range items {
		switch itemT := item.(type) {
		case value.StringValue:
			vals.Append(itemT.Val())
		case value.StringsValue:
			for _, sv := range itemT.Val() {
				vals.Append(sv)
			}
		case value.SliceValue:
			for _, sv := range itemT.Val() {
				vals.Append(sv.ToString())
			}
		}
	}

	if vals.Len() == 0 {
		return vals, true
	}
	hosts := value.NewStringsValue(make([]string, 0))
	for _, val := range vals.Val() {
		urlstr := strings.ToLower(val)
		if len(urlstr) < 8 {
			continue
		}
		if !strings.HasPrefix(urlstr, "http") {
			urlstr = "http://" + urlstr
		}
		if urlParsed, err := url.Parse(urlstr); err == nil {
			//u.Infof("url.parse: %#v", urlParsed)
			hosts.Append(urlParsed.Host)
		}
	}
	return hosts, true
}
Пример #5
0
	{`gt(toint(price),1)`, value.BoolValueTrue},

	{`contains("5tem",5)`, value.BoolValueTrue},
	{`contains("5item","item")`, value.BoolValueTrue},
	{`contains("the-hello",event)`, value.BoolValueTrue},
	{`contains("the-item",event)`, value.BoolValueFalse},
	{`contains(price,"$")`, value.BoolValueTrue},
	{`contains(url,"membership/all.html")`, value.BoolValueTrue},

	{`tolower("Apple")`, value.NewStringValue("apple")},

	{`join("apple", event, "oranges", "--")`, value.NewStringValue("apple--hello--oranges")},
	{`join(["apple","peach"], ",")`, value.NewStringValue("apple,peach")},
	{`join("apple","","peach",",")`, value.NewStringValue("apple,peach")},

	{`split("apples,oranges",",")`, value.NewStringsValue([]string{"apples", "oranges"})},

	{`replace("M20:30","M")`, value.NewStringValue("20:30")},
	{`replace("/search/for+stuff","/search/")`, value.NewStringValue("for+stuff")},

	{`oneof("apples","oranges")`, value.NewStringValue("apples")},
	{`oneof(notincontext,event)`, value.NewStringValue("hello")},

	{`any(5)`, value.BoolValueTrue},
	// TODO: {`any(0)`, value.BoolValueFalse},
	{`any("value")`, value.BoolValueTrue},
	{`any(event)`, value.BoolValueTrue},
	{`any(notrealfield)`, value.BoolValueFalse},

	{`all("Apple")`, value.BoolValueTrue},
	{`all("Apple")`, value.BoolValueTrue},
Пример #6
0
	{`tolower("Apple")`, value.NewStringValue("apple")},

	{`len(["5","6"])`, value.NewIntValue(2)},
	{`len("abc")`, value.NewIntValue(3)},
	{`len(split(reg_date,"/"))`, value.NewIntValue(3)},
	{`len(not_a_field)`, nil},
	{`len(not_a_field) >= 10`, value.BoolValueFalse},
	{`len("abc") >= 2`, value.BoolValueTrue},
	{`CHAR_LENGTH("abc") `, value.NewIntValue(3)},
	{`CHAR_LENGTH(CAST("abc" AS CHAR))`, value.NewIntValue(3)},

	{`join("apple", event, "oranges", "--")`, value.NewStringValue("apple--hello--oranges")},
	{`join(["apple","peach"], ",")`, value.NewStringValue("apple,peach")},
	{`join("apple","","peach",",")`, value.NewStringValue("apple,peach")},

	{`split("apples,oranges",",")`, value.NewStringsValue([]string{"apples", "oranges"})},

	{`replace("M20:30","M")`, value.NewStringValue("20:30")},
	{`replace("/search/for+stuff","/search/")`, value.NewStringValue("for+stuff")},
	{`replace("M20:30","M","")`, value.NewStringValue("20:30")},
	{`replace("M20:30","M","Hour ")`, value.NewStringValue("Hour 20:30")},

	{`oneof("apples","oranges")`, value.NewStringValue("apples")},
	{`oneof(notincontext,event)`, value.NewStringValue("hello")},

	{`any(5)`, value.BoolValueTrue},
	// TODO: {`any(0)`, value.BoolValueFalse},
	{`any("value")`, value.BoolValueTrue},
	{`any(event)`, value.BoolValueTrue},
	{`any(notrealfield)`, value.BoolValueFalse},
Пример #7
0
	builtins.LoadAllBuiltins()
}

var (
	t1, _ = dateparse.ParseAny("12/18/2019")
	// This is the message context which will be added to all tests below
	//  and be available to the VM runtime for evaluation by using
	//  key's such as "int5" or "user_id"
	msgContext = datasource.NewContextSimpleData(map[string]value.Value{
		"int5":    value.NewIntValue(5),
		"str5":    value.NewStringValue("5"),
		"created": value.NewTimeValue(t1),
		"bvalt":   value.NewBoolValue(true),
		"bvalf":   value.NewBoolValue(false),
		"user_id": value.NewStringValue("abc"),
		"urls":    value.NewStringsValue([]string{"abc", "123"}),
		"hits":    value.NewMapIntValue(map[string]int64{"google.com": 5, "bing.com": 1}),
		"email":   value.NewStringValue("*****@*****.**"),
	})
	vmTestsx = []vmTest{
		// Native LIKE keyword
		vmt(`["portland"] LIKE "*land"`, true, noError),
	}
	// list of tests
	vmTests = []vmTest{

		// Date math
		vmt(`created > "now-1M"`, true, noError),
		vmt(`now() > todate("01/01/2014")`, true, noError),
		vmt(`todate("now+3d") > now()`, true, noError),
		vmt(`created < 2032220220175`, true, noError), // Really not sure i want to support this?
Пример #8
0
// FilterFunc  Filter out Values that match specified list of match filter criteria
//
//   - Operates on MapValue (map[string]interface{}), StringsValue ([]string), or string
//   - takes N Filter Criteria
//   - supports Matching:      "filter*" // matches  "filter_x", "filterstuff"
//
//  -- Filter a map of values by key to remove certain keys
//    filter(match("topic_"),key_to_filter, key2_to_filter)  => {"goodkey": 22}, true
//
// -- Filter out VALUES (not keys) from a list of []string{} for a specific value
//    filter(split("apples,oranges",","),"ora*")  => ["apples"], true
//
// -- Filter out values for single strings
//    filter("apples","app*")      => []string{}, true
//
func FilterFunc(ctx expr.EvalContext, val value.Value, filterVals ...value.Value) (value.Value, bool) {

	filters := FiltersFromArgs(filterVals)

	//u.Debugf("Filter():  %T:%v   filters:%v", val, val, filters)
	switch val := val.(type) {
	case value.MapValue:

		mv := make(map[string]interface{})

		for rowKey, v := range val.Val() {
			filteredOut := false
			for _, filter := range filters {
				if strings.Contains(filter, "*") {
					match, _ := glob.Match(filter, rowKey)
					if match {
						filteredOut = true
						break
					}
				} else {
					if strings.HasPrefix(rowKey, filter) && v != nil {
						filteredOut = true
						break
					}
				}
			}
			if !filteredOut {
				mv[rowKey] = v.Value()
			}
		}

		return value.NewMapValue(mv), true

	case value.StringValue:
		anyMatches := false
		for _, filter := range filters {
			if strings.Contains(filter, "*") {
				match, _ := glob.Match(filter, val.Val())
				if match {
					anyMatches = true
					break
				}
			} else {
				if strings.HasPrefix(val.Val(), filter) {
					anyMatches = true
					break
				}
			}
		}
		if anyMatches {
			return value.NilValueVal, true
		}
		return val, true
	case value.StringsValue:
		lv := make([]string, 0, val.Len())
		for _, sv := range val.Val() {
			filteredOut := false
			for _, filter := range filters {
				if strings.Contains(filter, "*") {
					match, _ := glob.Match(filter, sv)
					if match {
						filteredOut = true
						break
					}
				} else {
					if strings.HasPrefix(sv, filter) && sv != "" {
						filteredOut = true
						break
					}
				}
			}
			if !filteredOut {
				lv = append(lv, sv)
			}
		}

		return value.NewStringsValue(lv), true

	default:
		u.Warnf("unsuported key type: %T %v", val, val)
	}

	//u.Warnf("could not find key: %T %v", item, item)
	return nil, false
}